├── .gitignore ├── LICENSE ├── README.md ├── backup.go ├── backup_test.go ├── callback.go ├── callback_test.go ├── convert.go ├── doc.go ├── error.go ├── error_test.go ├── examples └── main.go ├── go.mod ├── go.sum ├── sqlite3.go ├── sqlite3.h ├── sqlite3_context.go ├── sqlite3_func_crypt.go ├── sqlite3_func_crypt_test.go ├── sqlite3_go113_test.go ├── sqlite3_go18.go ├── sqlite3_go18_test.go ├── sqlite3_libsqlite3.go ├── sqlite3_load_extension.go ├── sqlite3_load_extension_omit.go ├── sqlite3_load_extension_test.go ├── sqlite3_opt_allow_uri_authority.go ├── sqlite3_opt_app_armor.go ├── sqlite3_opt_column_metadata.go ├── sqlite3_opt_column_metadata_test.go ├── sqlite3_opt_foreign_keys.go ├── sqlite3_opt_fts3_test.go ├── sqlite3_opt_fts5.go ├── sqlite3_opt_icu.go ├── sqlite3_opt_introspect.go ├── sqlite3_opt_json1.go ├── sqlite3_opt_preupdate.go ├── sqlite3_opt_preupdate_hook.go ├── sqlite3_opt_preupdate_hook_test.go ├── sqlite3_opt_preupdate_omit.go ├── sqlite3_opt_secure_delete.go ├── sqlite3_opt_secure_delete_fast.go ├── sqlite3_opt_stat4.go ├── sqlite3_opt_unlock_notify.c ├── sqlite3_opt_unlock_notify.go ├── sqlite3_opt_unlock_notify_test.go ├── sqlite3_opt_userauth.go ├── sqlite3_opt_userauth_omit.go ├── sqlite3_opt_userauth_test.go ├── sqlite3_opt_vacuum_full.go ├── sqlite3_opt_vacuum_incr.go ├── sqlite3_opt_vtable.go ├── sqlite3_opt_vtable_test.go ├── sqlite3_other.go ├── sqlite3_solaris.go ├── sqlite3_test.go ├── sqlite3_trace.go ├── sqlite3_type.go ├── sqlite3_usleep_windows.go ├── sqlite3_windows.go ├── sqlite3mc.c ├── sqlite3mc.h ├── static_mock.go ├── wxsqlite3 ├── aes_hardware.c ├── carray.c ├── carray.h ├── chacha20poly1305.c ├── cipher_chacha20.c ├── cipher_common.c ├── cipher_common.h ├── cipher_config.c ├── cipher_config.h ├── cipher_sds_rc4.c ├── cipher_sqlcipher.c ├── cipher_wxaes128.c ├── cipher_wxaes256.c ├── codec_algos.c ├── codecext.c ├── csv.c ├── extensionfunctions.c ├── fastpbkdf2.c ├── fastpbkdf2.h ├── fileio.c ├── filelist.md ├── md5.c ├── mystdint.h ├── regexp.c ├── rekeyvacuum.c ├── rijndael.c ├── rijndael.h ├── series.c ├── sha1.c ├── sha1.h ├── sha2.c ├── sha2.h ├── shathree.c ├── shell.c ├── sqlite3.c ├── sqlite3.h ├── sqlite370.ico ├── sqlite3ext.h ├── sqlite3mc.c ├── sqlite3mc.def ├── sqlite3mc.h ├── sqlite3mc.rc ├── sqlite3mc_config.h ├── sqlite3mc_shell.rc ├── sqlite3mc_version.h ├── sqlite3mc_vfs.c ├── sqlite3mc_vfs.h ├── sqlite3patched.c ├── sqlite3userauth.h ├── test_windirent.c ├── test_windirent.h ├── userauth.c ├── uuid.c └── vsv.c └── wxsqlite3_cgo.go /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019-2020 Ulrich Telle 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 背景 2 | 3 | 最近有个小项目需要用到SQLite数据库,go已经有现成的开源库可以实现,但是美中不足的是,开源版本并不支持数据库加密,这个直接在项目中使用,很明显是不行的。 4 | 5 | 秉承着能不造轮子就不造轮子的原则,在网上搜寻了一下,目前比较有知名度的加密开源实现分别是:wxSQLite3和sqlcipher。其中发现sqlcipher已经有go版本的轮子可以使用了,但是集成后,生成的数据库文件并不能用Navicat打开,到Navicat官网查询后,发现Navicat默认是使用*wxSQLite3* (128-bit AES) 进行加密实现的。为了后续数据查询方便,所以决定用wxSQLite3来实现加密,然而在网上找了许久,都没发现有go版本的wxSQLite3。 6 | 7 | 最后研究了一下go-sqlite3的实现方式,发现他其实是直接调用C版本的sqlite,那这时候事情就简单,我直接移花接木一下,把里面的C代码替换成wxSQLite3即可,所以就有了现在这个项目。 8 | 9 | 本项目代码主要是来自以下两个项目: 10 | 11 | - [https://github.com/mattn/go-sqlite3](https://github.com/mattn/go-sqlite3) 12 | - https://github.com/utelle/SQLite3MultipleCiphers 13 | 14 | # 安装 15 | 16 | ```go 17 | import "github.com/Jathon-yang/go-wxsqlite3" 18 | ``` 19 | 20 | # 使用 21 | 22 | ```go 23 | key := url.QueryEscape("123456") 24 | dbname := fmt.Sprintf("./foo.db?_db_key=%s", key) 25 | db, err := sql.Open("sqlite3", dbname) 26 | ``` 27 | 目前项目默认使用的加密算法是128-bit AES,如果想切换加密算法,可以修改 wxsqlite3_cgo.go 中 CODEC_TYPE 的值,目前支持以下几种加密算法: 28 | 29 | - CODEC_TYPE_AES128 30 | - CODEC_TYPE_AES256 31 | - CODEC_TYPE_CHACHA20 32 | - CODEC_TYPE_SQLCIPHER 33 | - CODEC_TYPE_RC4 -------------------------------------------------------------------------------- /backup.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | package sqlite3 7 | 8 | /* 9 | #ifndef USE_LIBSQLITE3 10 | #include "sqlite3-binding.h" 11 | #else 12 | #include 13 | #endif 14 | #include 15 | */ 16 | import "C" 17 | import ( 18 | "runtime" 19 | "unsafe" 20 | ) 21 | 22 | // SQLiteBackup implement interface of Backup. 23 | type SQLiteBackup struct { 24 | b *C.sqlite3_backup 25 | } 26 | 27 | // Backup make backup from src to dest. 28 | func (destConn *SQLiteConn) Backup(dest string, srcConn *SQLiteConn, src string) (*SQLiteBackup, error) { 29 | destptr := C.CString(dest) 30 | defer C.free(unsafe.Pointer(destptr)) 31 | srcptr := C.CString(src) 32 | defer C.free(unsafe.Pointer(srcptr)) 33 | 34 | if b := C.sqlite3_backup_init(destConn.db, destptr, srcConn.db, srcptr); b != nil { 35 | bb := &SQLiteBackup{b: b} 36 | runtime.SetFinalizer(bb, (*SQLiteBackup).Finish) 37 | return bb, nil 38 | } 39 | return nil, destConn.lastError() 40 | } 41 | 42 | // Step to backs up for one step. Calls the underlying `sqlite3_backup_step` 43 | // function. This function returns a boolean indicating if the backup is done 44 | // and an error signalling any other error. Done is returned if the underlying 45 | // C function returns SQLITE_DONE (Code 101) 46 | func (b *SQLiteBackup) Step(p int) (bool, error) { 47 | ret := C.sqlite3_backup_step(b.b, C.int(p)) 48 | if ret == C.SQLITE_DONE { 49 | return true, nil 50 | } else if ret != 0 && ret != C.SQLITE_LOCKED && ret != C.SQLITE_BUSY { 51 | return false, Error{Code: ErrNo(ret)} 52 | } 53 | return false, nil 54 | } 55 | 56 | // Remaining return whether have the rest for backup. 57 | func (b *SQLiteBackup) Remaining() int { 58 | return int(C.sqlite3_backup_remaining(b.b)) 59 | } 60 | 61 | // PageCount return count of pages. 62 | func (b *SQLiteBackup) PageCount() int { 63 | return int(C.sqlite3_backup_pagecount(b.b)) 64 | } 65 | 66 | // Finish close backup. 67 | func (b *SQLiteBackup) Finish() error { 68 | return b.Close() 69 | } 70 | 71 | // Close close backup. 72 | func (b *SQLiteBackup) Close() error { 73 | ret := C.sqlite3_backup_finish(b.b) 74 | 75 | // sqlite3_backup_finish() never fails, it just returns the 76 | // error code from previous operations, so clean up before 77 | // checking and returning an error 78 | b.b = nil 79 | runtime.SetFinalizer(b, nil) 80 | 81 | if ret != 0 { 82 | return Error{Code: ErrNo(ret)} 83 | } 84 | return nil 85 | } 86 | -------------------------------------------------------------------------------- /callback_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // +build cgo 7 | 8 | package sqlite3 9 | 10 | import ( 11 | "errors" 12 | "math" 13 | "reflect" 14 | "testing" 15 | ) 16 | 17 | func TestCallbackArgCast(t *testing.T) { 18 | intConv := callbackSyntheticForTests(reflect.ValueOf(int64(math.MaxInt64)), nil) 19 | floatConv := callbackSyntheticForTests(reflect.ValueOf(float64(math.MaxFloat64)), nil) 20 | errConv := callbackSyntheticForTests(reflect.Value{}, errors.New("test")) 21 | 22 | tests := []struct { 23 | f callbackArgConverter 24 | o reflect.Value 25 | }{ 26 | {intConv, reflect.ValueOf(int8(-1))}, 27 | {intConv, reflect.ValueOf(int16(-1))}, 28 | {intConv, reflect.ValueOf(int32(-1))}, 29 | {intConv, reflect.ValueOf(uint8(math.MaxUint8))}, 30 | {intConv, reflect.ValueOf(uint16(math.MaxUint16))}, 31 | {intConv, reflect.ValueOf(uint32(math.MaxUint32))}, 32 | // Special case, int64->uint64 is only 1<<63 - 1, not 1<<64 - 1 33 | {intConv, reflect.ValueOf(uint64(math.MaxInt64))}, 34 | {floatConv, reflect.ValueOf(float32(math.Inf(1)))}, 35 | } 36 | 37 | for _, test := range tests { 38 | conv := callbackArgCast{test.f, test.o.Type()} 39 | val, err := conv.Run(nil) 40 | if err != nil { 41 | t.Errorf("Couldn't convert to %s: %s", test.o.Type(), err) 42 | } else if !reflect.DeepEqual(val.Interface(), test.o.Interface()) { 43 | t.Errorf("Unexpected result from converting to %s: got %v, want %v", test.o.Type(), val.Interface(), test.o.Interface()) 44 | } 45 | } 46 | 47 | conv := callbackArgCast{errConv, reflect.TypeOf(int8(0))} 48 | _, err := conv.Run(nil) 49 | if err == nil { 50 | t.Errorf("Expected error during callbackArgCast, but got none") 51 | } 52 | } 53 | 54 | func TestCallbackConverters(t *testing.T) { 55 | tests := []struct { 56 | v interface{} 57 | err bool 58 | }{ 59 | // Unfortunately, we can't tell which converter was returned, 60 | // but we can at least check which types can be converted. 61 | {[]byte{0}, false}, 62 | {"text", false}, 63 | {true, false}, 64 | {int8(0), false}, 65 | {int16(0), false}, 66 | {int32(0), false}, 67 | {int64(0), false}, 68 | {uint8(0), false}, 69 | {uint16(0), false}, 70 | {uint32(0), false}, 71 | {uint64(0), false}, 72 | {int(0), false}, 73 | {uint(0), false}, 74 | {float64(0), false}, 75 | {float32(0), false}, 76 | 77 | {func() {}, true}, 78 | {complex64(complex(0, 0)), true}, 79 | {complex128(complex(0, 0)), true}, 80 | {struct{}{}, true}, 81 | {map[string]string{}, true}, 82 | {[]string{}, true}, 83 | {(*int8)(nil), true}, 84 | {make(chan int), true}, 85 | } 86 | 87 | for _, test := range tests { 88 | _, err := callbackArg(reflect.TypeOf(test.v)) 89 | if test.err && err == nil { 90 | t.Errorf("Expected an error when converting %s, got no error", reflect.TypeOf(test.v)) 91 | } else if !test.err && err != nil { 92 | t.Errorf("Expected converter when converting %s, got error: %s", reflect.TypeOf(test.v), err) 93 | } 94 | } 95 | 96 | for _, test := range tests { 97 | _, err := callbackRet(reflect.TypeOf(test.v)) 98 | if test.err && err == nil { 99 | t.Errorf("Expected an error when converting %s, got no error", reflect.TypeOf(test.v)) 100 | } else if !test.err && err != nil { 101 | t.Errorf("Expected converter when converting %s, got error: %s", reflect.TypeOf(test.v), err) 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /convert.go: -------------------------------------------------------------------------------- 1 | // Extracted from Go database/sql source code 2 | 3 | // Copyright 2011 The Go Authors. All rights reserved. 4 | // Use of this source code is governed by a BSD-style 5 | // license that can be found in the LICENSE file. 6 | 7 | // Type conversions for Scan. 8 | 9 | package sqlite3 10 | 11 | import ( 12 | "database/sql" 13 | "database/sql/driver" 14 | "errors" 15 | "fmt" 16 | "reflect" 17 | "strconv" 18 | "time" 19 | ) 20 | 21 | var errNilPtr = errors.New("destination pointer is nil") // embedded in descriptive error 22 | 23 | // convertAssign copies to dest the value in src, converting it if possible. 24 | // An error is returned if the copy would result in loss of information. 25 | // dest should be a pointer type. 26 | func convertAssign(dest, src interface{}) error { 27 | // Common cases, without reflect. 28 | switch s := src.(type) { 29 | case string: 30 | switch d := dest.(type) { 31 | case *string: 32 | if d == nil { 33 | return errNilPtr 34 | } 35 | *d = s 36 | return nil 37 | case *[]byte: 38 | if d == nil { 39 | return errNilPtr 40 | } 41 | *d = []byte(s) 42 | return nil 43 | case *sql.RawBytes: 44 | if d == nil { 45 | return errNilPtr 46 | } 47 | *d = append((*d)[:0], s...) 48 | return nil 49 | } 50 | case []byte: 51 | switch d := dest.(type) { 52 | case *string: 53 | if d == nil { 54 | return errNilPtr 55 | } 56 | *d = string(s) 57 | return nil 58 | case *interface{}: 59 | if d == nil { 60 | return errNilPtr 61 | } 62 | *d = cloneBytes(s) 63 | return nil 64 | case *[]byte: 65 | if d == nil { 66 | return errNilPtr 67 | } 68 | *d = cloneBytes(s) 69 | return nil 70 | case *sql.RawBytes: 71 | if d == nil { 72 | return errNilPtr 73 | } 74 | *d = s 75 | return nil 76 | } 77 | case time.Time: 78 | switch d := dest.(type) { 79 | case *time.Time: 80 | *d = s 81 | return nil 82 | case *string: 83 | *d = s.Format(time.RFC3339Nano) 84 | return nil 85 | case *[]byte: 86 | if d == nil { 87 | return errNilPtr 88 | } 89 | *d = []byte(s.Format(time.RFC3339Nano)) 90 | return nil 91 | case *sql.RawBytes: 92 | if d == nil { 93 | return errNilPtr 94 | } 95 | *d = s.AppendFormat((*d)[:0], time.RFC3339Nano) 96 | return nil 97 | } 98 | case nil: 99 | switch d := dest.(type) { 100 | case *interface{}: 101 | if d == nil { 102 | return errNilPtr 103 | } 104 | *d = nil 105 | return nil 106 | case *[]byte: 107 | if d == nil { 108 | return errNilPtr 109 | } 110 | *d = nil 111 | return nil 112 | case *sql.RawBytes: 113 | if d == nil { 114 | return errNilPtr 115 | } 116 | *d = nil 117 | return nil 118 | } 119 | } 120 | 121 | var sv reflect.Value 122 | 123 | switch d := dest.(type) { 124 | case *string: 125 | sv = reflect.ValueOf(src) 126 | switch sv.Kind() { 127 | case reflect.Bool, 128 | reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, 129 | reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, 130 | reflect.Float32, reflect.Float64: 131 | *d = asString(src) 132 | return nil 133 | } 134 | case *[]byte: 135 | sv = reflect.ValueOf(src) 136 | if b, ok := asBytes(nil, sv); ok { 137 | *d = b 138 | return nil 139 | } 140 | case *sql.RawBytes: 141 | sv = reflect.ValueOf(src) 142 | if b, ok := asBytes([]byte(*d)[:0], sv); ok { 143 | *d = sql.RawBytes(b) 144 | return nil 145 | } 146 | case *bool: 147 | bv, err := driver.Bool.ConvertValue(src) 148 | if err == nil { 149 | *d = bv.(bool) 150 | } 151 | return err 152 | case *interface{}: 153 | *d = src 154 | return nil 155 | } 156 | 157 | if scanner, ok := dest.(sql.Scanner); ok { 158 | return scanner.Scan(src) 159 | } 160 | 161 | dpv := reflect.ValueOf(dest) 162 | if dpv.Kind() != reflect.Ptr { 163 | return errors.New("destination not a pointer") 164 | } 165 | if dpv.IsNil() { 166 | return errNilPtr 167 | } 168 | 169 | if !sv.IsValid() { 170 | sv = reflect.ValueOf(src) 171 | } 172 | 173 | dv := reflect.Indirect(dpv) 174 | if sv.IsValid() && sv.Type().AssignableTo(dv.Type()) { 175 | switch b := src.(type) { 176 | case []byte: 177 | dv.Set(reflect.ValueOf(cloneBytes(b))) 178 | default: 179 | dv.Set(sv) 180 | } 181 | return nil 182 | } 183 | 184 | if dv.Kind() == sv.Kind() && sv.Type().ConvertibleTo(dv.Type()) { 185 | dv.Set(sv.Convert(dv.Type())) 186 | return nil 187 | } 188 | 189 | // The following conversions use a string value as an intermediate representation 190 | // to convert between various numeric types. 191 | // 192 | // This also allows scanning into user defined types such as "type Int int64". 193 | // For symmetry, also check for string destination types. 194 | switch dv.Kind() { 195 | case reflect.Ptr: 196 | if src == nil { 197 | dv.Set(reflect.Zero(dv.Type())) 198 | return nil 199 | } 200 | dv.Set(reflect.New(dv.Type().Elem())) 201 | return convertAssign(dv.Interface(), src) 202 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 203 | s := asString(src) 204 | i64, err := strconv.ParseInt(s, 10, dv.Type().Bits()) 205 | if err != nil { 206 | err = strconvErr(err) 207 | return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", src, s, dv.Kind(), err) 208 | } 209 | dv.SetInt(i64) 210 | return nil 211 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 212 | s := asString(src) 213 | u64, err := strconv.ParseUint(s, 10, dv.Type().Bits()) 214 | if err != nil { 215 | err = strconvErr(err) 216 | return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", src, s, dv.Kind(), err) 217 | } 218 | dv.SetUint(u64) 219 | return nil 220 | case reflect.Float32, reflect.Float64: 221 | s := asString(src) 222 | f64, err := strconv.ParseFloat(s, dv.Type().Bits()) 223 | if err != nil { 224 | err = strconvErr(err) 225 | return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", src, s, dv.Kind(), err) 226 | } 227 | dv.SetFloat(f64) 228 | return nil 229 | case reflect.String: 230 | switch v := src.(type) { 231 | case string: 232 | dv.SetString(v) 233 | return nil 234 | case []byte: 235 | dv.SetString(string(v)) 236 | return nil 237 | } 238 | } 239 | 240 | return fmt.Errorf("unsupported Scan, storing driver.Value type %T into type %T", src, dest) 241 | } 242 | 243 | func strconvErr(err error) error { 244 | if ne, ok := err.(*strconv.NumError); ok { 245 | return ne.Err 246 | } 247 | return err 248 | } 249 | 250 | func cloneBytes(b []byte) []byte { 251 | if b == nil { 252 | return nil 253 | } 254 | c := make([]byte, len(b)) 255 | copy(c, b) 256 | return c 257 | } 258 | 259 | func asString(src interface{}) string { 260 | switch v := src.(type) { 261 | case string: 262 | return v 263 | case []byte: 264 | return string(v) 265 | } 266 | rv := reflect.ValueOf(src) 267 | switch rv.Kind() { 268 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 269 | return strconv.FormatInt(rv.Int(), 10) 270 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 271 | return strconv.FormatUint(rv.Uint(), 10) 272 | case reflect.Float64: 273 | return strconv.FormatFloat(rv.Float(), 'g', -1, 64) 274 | case reflect.Float32: 275 | return strconv.FormatFloat(rv.Float(), 'g', -1, 32) 276 | case reflect.Bool: 277 | return strconv.FormatBool(rv.Bool()) 278 | } 279 | return fmt.Sprintf("%v", src) 280 | } 281 | 282 | func asBytes(buf []byte, rv reflect.Value) (b []byte, ok bool) { 283 | switch rv.Kind() { 284 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 285 | return strconv.AppendInt(buf, rv.Int(), 10), true 286 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 287 | return strconv.AppendUint(buf, rv.Uint(), 10), true 288 | case reflect.Float32: 289 | return strconv.AppendFloat(buf, rv.Float(), 'g', -1, 32), true 290 | case reflect.Float64: 291 | return strconv.AppendFloat(buf, rv.Float(), 'g', -1, 64), true 292 | case reflect.Bool: 293 | return strconv.AppendBool(buf, rv.Bool()), true 294 | case reflect.String: 295 | s := rv.String() 296 | return append(buf, s...), true 297 | } 298 | return 299 | } 300 | -------------------------------------------------------------------------------- /doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package sqlite3 provides interface to SQLite3 databases. 3 | 4 | This works as a driver for database/sql. 5 | 6 | Installation 7 | 8 | go get github.com/Jathon-yang/go-wxsqlite3 9 | */ 10 | package sqlite3 11 | -------------------------------------------------------------------------------- /error.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | package sqlite3 7 | 8 | /* 9 | #ifndef USE_LIBSQLITE3 10 | #include "sqlite3-binding.h" 11 | #else 12 | #include 13 | #endif 14 | */ 15 | import "C" 16 | import "syscall" 17 | 18 | // ErrNo inherit errno. 19 | type ErrNo int 20 | 21 | // ErrNoMask is mask code. 22 | const ErrNoMask C.int = 0xff 23 | 24 | // ErrNoExtended is extended errno. 25 | type ErrNoExtended int 26 | 27 | // Error implement sqlite error code. 28 | type Error struct { 29 | Code ErrNo /* The error code returned by SQLite */ 30 | ExtendedCode ErrNoExtended /* The extended error code returned by SQLite */ 31 | SystemErrno syscall.Errno /* The system errno returned by the OS through SQLite, if applicable */ 32 | err string /* The error string returned by sqlite3_errmsg(), 33 | this usually contains more specific details. */ 34 | } 35 | 36 | // result codes from http://www.sqlite.org/c3ref/c_abort.html 37 | var ( 38 | ErrError = ErrNo(1) /* SQL error or missing database */ 39 | ErrInternal = ErrNo(2) /* Internal logic error in SQLite */ 40 | ErrPerm = ErrNo(3) /* Access permission denied */ 41 | ErrAbort = ErrNo(4) /* Callback routine requested an abort */ 42 | ErrBusy = ErrNo(5) /* The database file is locked */ 43 | ErrLocked = ErrNo(6) /* A table in the database is locked */ 44 | ErrNomem = ErrNo(7) /* A malloc() failed */ 45 | ErrReadonly = ErrNo(8) /* Attempt to write a readonly database */ 46 | ErrInterrupt = ErrNo(9) /* Operation terminated by sqlite3_interrupt() */ 47 | ErrIoErr = ErrNo(10) /* Some kind of disk I/O error occurred */ 48 | ErrCorrupt = ErrNo(11) /* The database disk image is malformed */ 49 | ErrNotFound = ErrNo(12) /* Unknown opcode in sqlite3_file_control() */ 50 | ErrFull = ErrNo(13) /* Insertion failed because database is full */ 51 | ErrCantOpen = ErrNo(14) /* Unable to open the database file */ 52 | ErrProtocol = ErrNo(15) /* Database lock protocol error */ 53 | ErrEmpty = ErrNo(16) /* Database is empty */ 54 | ErrSchema = ErrNo(17) /* The database schema changed */ 55 | ErrTooBig = ErrNo(18) /* String or BLOB exceeds size limit */ 56 | ErrConstraint = ErrNo(19) /* Abort due to constraint violation */ 57 | ErrMismatch = ErrNo(20) /* Data type mismatch */ 58 | ErrMisuse = ErrNo(21) /* Library used incorrectly */ 59 | ErrNoLFS = ErrNo(22) /* Uses OS features not supported on host */ 60 | ErrAuth = ErrNo(23) /* Authorization denied */ 61 | ErrFormat = ErrNo(24) /* Auxiliary database format error */ 62 | ErrRange = ErrNo(25) /* 2nd parameter to sqlite3_bind out of range */ 63 | ErrNotADB = ErrNo(26) /* File opened that is not a database file */ 64 | ErrNotice = ErrNo(27) /* Notifications from sqlite3_log() */ 65 | ErrWarning = ErrNo(28) /* Warnings from sqlite3_log() */ 66 | ) 67 | 68 | // Error return error message from errno. 69 | func (err ErrNo) Error() string { 70 | return Error{Code: err}.Error() 71 | } 72 | 73 | // Extend return extended errno. 74 | func (err ErrNo) Extend(by int) ErrNoExtended { 75 | return ErrNoExtended(int(err) | (by << 8)) 76 | } 77 | 78 | // Error return error message that is extended code. 79 | func (err ErrNoExtended) Error() string { 80 | return Error{Code: ErrNo(C.int(err) & ErrNoMask), ExtendedCode: err}.Error() 81 | } 82 | 83 | func (err Error) Error() string { 84 | var str string 85 | if err.err != "" { 86 | str = err.err 87 | } else { 88 | str = C.GoString(C.sqlite3_errstr(C.int(err.Code))) 89 | } 90 | if err.SystemErrno != 0 { 91 | str += ": " + err.SystemErrno.Error() 92 | } 93 | return str 94 | } 95 | 96 | // result codes from http://www.sqlite.org/c3ref/c_abort_rollback.html 97 | var ( 98 | ErrIoErrRead = ErrIoErr.Extend(1) 99 | ErrIoErrShortRead = ErrIoErr.Extend(2) 100 | ErrIoErrWrite = ErrIoErr.Extend(3) 101 | ErrIoErrFsync = ErrIoErr.Extend(4) 102 | ErrIoErrDirFsync = ErrIoErr.Extend(5) 103 | ErrIoErrTruncate = ErrIoErr.Extend(6) 104 | ErrIoErrFstat = ErrIoErr.Extend(7) 105 | ErrIoErrUnlock = ErrIoErr.Extend(8) 106 | ErrIoErrRDlock = ErrIoErr.Extend(9) 107 | ErrIoErrDelete = ErrIoErr.Extend(10) 108 | ErrIoErrBlocked = ErrIoErr.Extend(11) 109 | ErrIoErrNoMem = ErrIoErr.Extend(12) 110 | ErrIoErrAccess = ErrIoErr.Extend(13) 111 | ErrIoErrCheckReservedLock = ErrIoErr.Extend(14) 112 | ErrIoErrLock = ErrIoErr.Extend(15) 113 | ErrIoErrClose = ErrIoErr.Extend(16) 114 | ErrIoErrDirClose = ErrIoErr.Extend(17) 115 | ErrIoErrSHMOpen = ErrIoErr.Extend(18) 116 | ErrIoErrSHMSize = ErrIoErr.Extend(19) 117 | ErrIoErrSHMLock = ErrIoErr.Extend(20) 118 | ErrIoErrSHMMap = ErrIoErr.Extend(21) 119 | ErrIoErrSeek = ErrIoErr.Extend(22) 120 | ErrIoErrDeleteNoent = ErrIoErr.Extend(23) 121 | ErrIoErrMMap = ErrIoErr.Extend(24) 122 | ErrIoErrGetTempPath = ErrIoErr.Extend(25) 123 | ErrIoErrConvPath = ErrIoErr.Extend(26) 124 | ErrLockedSharedCache = ErrLocked.Extend(1) 125 | ErrBusyRecovery = ErrBusy.Extend(1) 126 | ErrBusySnapshot = ErrBusy.Extend(2) 127 | ErrCantOpenNoTempDir = ErrCantOpen.Extend(1) 128 | ErrCantOpenIsDir = ErrCantOpen.Extend(2) 129 | ErrCantOpenFullPath = ErrCantOpen.Extend(3) 130 | ErrCantOpenConvPath = ErrCantOpen.Extend(4) 131 | ErrCorruptVTab = ErrCorrupt.Extend(1) 132 | ErrReadonlyRecovery = ErrReadonly.Extend(1) 133 | ErrReadonlyCantLock = ErrReadonly.Extend(2) 134 | ErrReadonlyRollback = ErrReadonly.Extend(3) 135 | ErrReadonlyDbMoved = ErrReadonly.Extend(4) 136 | ErrAbortRollback = ErrAbort.Extend(2) 137 | ErrConstraintCheck = ErrConstraint.Extend(1) 138 | ErrConstraintCommitHook = ErrConstraint.Extend(2) 139 | ErrConstraintForeignKey = ErrConstraint.Extend(3) 140 | ErrConstraintFunction = ErrConstraint.Extend(4) 141 | ErrConstraintNotNull = ErrConstraint.Extend(5) 142 | ErrConstraintPrimaryKey = ErrConstraint.Extend(6) 143 | ErrConstraintTrigger = ErrConstraint.Extend(7) 144 | ErrConstraintUnique = ErrConstraint.Extend(8) 145 | ErrConstraintVTab = ErrConstraint.Extend(9) 146 | ErrConstraintRowID = ErrConstraint.Extend(10) 147 | ErrNoticeRecoverWAL = ErrNotice.Extend(1) 148 | ErrNoticeRecoverRollback = ErrNotice.Extend(2) 149 | ErrWarningAutoIndex = ErrWarning.Extend(1) 150 | ) 151 | -------------------------------------------------------------------------------- /error_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // +build cgo 7 | 8 | package sqlite3 9 | 10 | import ( 11 | "database/sql" 12 | "io/ioutil" 13 | "os" 14 | "path" 15 | "testing" 16 | ) 17 | 18 | func TestSimpleError(t *testing.T) { 19 | e := ErrError.Error() 20 | if e != "SQL logic error or missing database" && e != "SQL logic error" { 21 | t.Error("wrong error code: " + e) 22 | } 23 | } 24 | 25 | func TestCorruptDbErrors(t *testing.T) { 26 | dirName, err := ioutil.TempDir("", "sqlite3") 27 | if err != nil { 28 | t.Fatal(err) 29 | } 30 | defer os.RemoveAll(dirName) 31 | 32 | dbFileName := path.Join(dirName, "test.db") 33 | f, err := os.Create(dbFileName) 34 | if err != nil { 35 | t.Error(err) 36 | } 37 | f.Write([]byte{1, 2, 3, 4, 5}) 38 | f.Close() 39 | 40 | db, err := sql.Open("sqlite3", dbFileName) 41 | if err == nil { 42 | _, err = db.Exec("drop table foo") 43 | } 44 | 45 | sqliteErr := err.(Error) 46 | if sqliteErr.Code != ErrNotADB { 47 | t.Error("wrong error code for corrupted DB") 48 | } 49 | if err.Error() == "" { 50 | t.Error("wrong error string for corrupted DB") 51 | } 52 | db.Close() 53 | } 54 | 55 | func TestSqlLogicErrors(t *testing.T) { 56 | dirName, err := ioutil.TempDir("", "sqlite3") 57 | if err != nil { 58 | t.Fatal(err) 59 | } 60 | defer os.RemoveAll(dirName) 61 | 62 | dbFileName := path.Join(dirName, "test.db") 63 | db, err := sql.Open("sqlite3", dbFileName) 64 | if err != nil { 65 | t.Error(err) 66 | } 67 | defer db.Close() 68 | 69 | _, err = db.Exec("CREATE TABLE Foo (id INTEGER PRIMARY KEY)") 70 | if err != nil { 71 | t.Error(err) 72 | } 73 | 74 | const expectedErr = "table Foo already exists" 75 | _, err = db.Exec("CREATE TABLE Foo (id INTEGER PRIMARY KEY)") 76 | if err.Error() != expectedErr { 77 | t.Errorf("Unexpected error: %s, expected %s", err.Error(), expectedErr) 78 | } 79 | 80 | } 81 | 82 | func TestExtendedErrorCodes_ForeignKey(t *testing.T) { 83 | dirName, err := ioutil.TempDir("", "sqlite3-err") 84 | if err != nil { 85 | t.Fatal(err) 86 | } 87 | defer os.RemoveAll(dirName) 88 | 89 | dbFileName := path.Join(dirName, "test.db") 90 | db, err := sql.Open("sqlite3", dbFileName) 91 | if err != nil { 92 | t.Error(err) 93 | } 94 | defer db.Close() 95 | 96 | _, err = db.Exec("PRAGMA foreign_keys=ON;") 97 | if err != nil { 98 | t.Errorf("PRAGMA foreign_keys=ON: %v", err) 99 | } 100 | 101 | _, err = db.Exec(`CREATE TABLE Foo ( 102 | id INTEGER PRIMARY KEY AUTOINCREMENT, 103 | value INTEGER NOT NULL, 104 | ref INTEGER NULL REFERENCES Foo (id), 105 | UNIQUE(value) 106 | );`) 107 | if err != nil { 108 | t.Error(err) 109 | } 110 | 111 | _, err = db.Exec("INSERT INTO Foo (ref, value) VALUES (100, 100);") 112 | if err == nil { 113 | t.Error("No error!") 114 | } else { 115 | sqliteErr := err.(Error) 116 | if sqliteErr.Code != ErrConstraint { 117 | t.Errorf("Wrong basic error code: %d != %d", 118 | sqliteErr.Code, ErrConstraint) 119 | } 120 | if sqliteErr.ExtendedCode != ErrConstraintForeignKey { 121 | t.Errorf("Wrong extended error code: %d != %d", 122 | sqliteErr.ExtendedCode, ErrConstraintForeignKey) 123 | } 124 | } 125 | 126 | } 127 | 128 | func TestExtendedErrorCodes_NotNull(t *testing.T) { 129 | dirName, err := ioutil.TempDir("", "sqlite3-err") 130 | if err != nil { 131 | t.Fatal(err) 132 | } 133 | defer os.RemoveAll(dirName) 134 | 135 | dbFileName := path.Join(dirName, "test.db") 136 | db, err := sql.Open("sqlite3", dbFileName) 137 | if err != nil { 138 | t.Error(err) 139 | } 140 | defer db.Close() 141 | 142 | _, err = db.Exec("PRAGMA foreign_keys=ON;") 143 | if err != nil { 144 | t.Errorf("PRAGMA foreign_keys=ON: %v", err) 145 | } 146 | 147 | _, err = db.Exec(`CREATE TABLE Foo ( 148 | id INTEGER PRIMARY KEY AUTOINCREMENT, 149 | value INTEGER NOT NULL, 150 | ref INTEGER NULL REFERENCES Foo (id), 151 | UNIQUE(value) 152 | );`) 153 | if err != nil { 154 | t.Error(err) 155 | } 156 | 157 | res, err := db.Exec("INSERT INTO Foo (value) VALUES (100);") 158 | if err != nil { 159 | t.Fatalf("Creating first row: %v", err) 160 | } 161 | 162 | id, err := res.LastInsertId() 163 | if err != nil { 164 | t.Fatalf("Retrieving last insert id: %v", err) 165 | } 166 | 167 | _, err = db.Exec("INSERT INTO Foo (ref) VALUES (?);", id) 168 | if err == nil { 169 | t.Error("No error!") 170 | } else { 171 | sqliteErr := err.(Error) 172 | if sqliteErr.Code != ErrConstraint { 173 | t.Errorf("Wrong basic error code: %d != %d", 174 | sqliteErr.Code, ErrConstraint) 175 | } 176 | if sqliteErr.ExtendedCode != ErrConstraintNotNull { 177 | t.Errorf("Wrong extended error code: %d != %d", 178 | sqliteErr.ExtendedCode, ErrConstraintNotNull) 179 | } 180 | } 181 | 182 | } 183 | 184 | func TestExtendedErrorCodes_Unique(t *testing.T) { 185 | dirName, err := ioutil.TempDir("", "sqlite3-err") 186 | if err != nil { 187 | t.Fatal(err) 188 | } 189 | defer os.RemoveAll(dirName) 190 | 191 | dbFileName := path.Join(dirName, "test.db") 192 | db, err := sql.Open("sqlite3", dbFileName) 193 | if err != nil { 194 | t.Error(err) 195 | } 196 | defer db.Close() 197 | 198 | _, err = db.Exec("PRAGMA foreign_keys=ON;") 199 | if err != nil { 200 | t.Errorf("PRAGMA foreign_keys=ON: %v", err) 201 | } 202 | 203 | _, err = db.Exec(`CREATE TABLE Foo ( 204 | id INTEGER PRIMARY KEY AUTOINCREMENT, 205 | value INTEGER NOT NULL, 206 | ref INTEGER NULL REFERENCES Foo (id), 207 | UNIQUE(value) 208 | );`) 209 | if err != nil { 210 | t.Error(err) 211 | } 212 | 213 | res, err := db.Exec("INSERT INTO Foo (value) VALUES (100);") 214 | if err != nil { 215 | t.Fatalf("Creating first row: %v", err) 216 | } 217 | 218 | id, err := res.LastInsertId() 219 | if err != nil { 220 | t.Fatalf("Retrieving last insert id: %v", err) 221 | } 222 | 223 | _, err = db.Exec("INSERT INTO Foo (ref, value) VALUES (?, 100);", id) 224 | if err == nil { 225 | t.Error("No error!") 226 | } else { 227 | sqliteErr := err.(Error) 228 | if sqliteErr.Code != ErrConstraint { 229 | t.Errorf("Wrong basic error code: %d != %d", 230 | sqliteErr.Code, ErrConstraint) 231 | } 232 | if sqliteErr.ExtendedCode != ErrConstraintUnique { 233 | t.Errorf("Wrong extended error code: %d != %d", 234 | sqliteErr.ExtendedCode, ErrConstraintUnique) 235 | } 236 | extended := sqliteErr.Code.Extend(3).Error() 237 | expected := "constraint failed" 238 | if extended != expected { 239 | t.Errorf("Wrong basic error code: %q != %q", 240 | extended, expected) 241 | } 242 | } 243 | } 244 | 245 | func TestError_SystemErrno(t *testing.T) { 246 | _, n, _ := Version() 247 | if n < 3012000 { 248 | t.Skip("sqlite3_system_errno requires sqlite3 >= 3.12.0") 249 | } 250 | 251 | // open a non-existent database in read-only mode so we get an IO error. 252 | db, err := sql.Open("sqlite3", "file:nonexistent.db?mode=ro") 253 | if err != nil { 254 | t.Fatal(err) 255 | } 256 | defer db.Close() 257 | 258 | err = db.Ping() 259 | if err == nil { 260 | t.Fatal("expected error pinging read-only non-existent database, but got nil") 261 | } 262 | 263 | serr, ok := err.(Error) 264 | if !ok { 265 | t.Fatalf("expected error to be of type Error, but got %[1]T %[1]v", err) 266 | } 267 | 268 | if serr.SystemErrno == 0 { 269 | t.Fatal("expected SystemErrno to be set") 270 | } 271 | 272 | if !os.IsNotExist(serr.SystemErrno) { 273 | t.Errorf("expected SystemErrno to be a not exists error, but got %v", serr.SystemErrno) 274 | } 275 | } 276 | -------------------------------------------------------------------------------- /examples/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "database/sql" 5 | "fmt" 6 | "log" 7 | "net/url" 8 | "os" 9 | _ "github.com/Jathon-yang/go-wxsqlite3" 10 | ) 11 | 12 | func main() { 13 | os.Remove("./foo.db") 14 | 15 | key := url.QueryEscape("123456") 16 | dbname := fmt.Sprintf("./foo.db?_db_key=%s", key) 17 | db, err := sql.Open("sqlite3", dbname) 18 | 19 | 20 | //db, err := sql.Open("sqlite3", "./foo.db") 21 | if err != nil { 22 | log.Fatal(err) 23 | return 24 | } 25 | defer db.Close() 26 | 27 | sqlStmt := ` 28 | create table foo (id integer not null primary key, name text); 29 | delete from foo; 30 | ` 31 | _, err = db.Exec(sqlStmt) 32 | if err != nil { 33 | log.Printf("%q: %s\n", err, sqlStmt) 34 | return 35 | } 36 | 37 | tx, err := db.Begin() 38 | if err != nil { 39 | log.Fatal(err) 40 | } 41 | stmt, err := tx.Prepare("insert into foo(id, name) values(?, ?)") 42 | if err != nil { 43 | log.Fatal(err) 44 | } 45 | defer stmt.Close() 46 | for i := 0; i < 100; i++ { 47 | _, err = stmt.Exec(i, fmt.Sprintf("こんにちわ世界%03d", i)) 48 | if err != nil { 49 | log.Fatal(err) 50 | } 51 | } 52 | tx.Commit() 53 | 54 | rows, err := db.Query("select id, name from foo") 55 | if err != nil { 56 | log.Fatal(err) 57 | } 58 | defer rows.Close() 59 | for rows.Next() { 60 | var id int 61 | var name string 62 | err = rows.Scan(&id, &name) 63 | if err != nil { 64 | log.Fatal(err) 65 | } 66 | fmt.Println(id, name) 67 | } 68 | err = rows.Err() 69 | if err != nil { 70 | log.Fatal(err) 71 | } 72 | 73 | stmt, err = db.Prepare("select name from foo where id = ?") 74 | if err != nil { 75 | log.Fatal(err) 76 | } 77 | defer stmt.Close() 78 | var name string 79 | err = stmt.QueryRow("3").Scan(&name) 80 | if err != nil { 81 | log.Fatal(err) 82 | } 83 | fmt.Println(name) 84 | 85 | _, err = db.Exec("delete from foo") 86 | if err != nil { 87 | log.Fatal(err) 88 | } 89 | 90 | _, err = db.Exec("insert into foo(id, name) values(1, 'foo'), (2, 'bar'), (3, 'baz')") 91 | if err != nil { 92 | log.Fatal(err) 93 | } 94 | 95 | rows, err = db.Query("select id, name from foo") 96 | if err != nil { 97 | log.Fatal(err) 98 | } 99 | defer rows.Close() 100 | for rows.Next() { 101 | var id int 102 | var name string 103 | err = rows.Scan(&id, &name) 104 | if err != nil { 105 | log.Fatal(err) 106 | } 107 | fmt.Println(id, name) 108 | } 109 | err = rows.Err() 110 | if err != nil { 111 | log.Fatal(err) 112 | } 113 | } -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/Jathon-yang/go-wxsqlite3 2 | 3 | go 1.12 4 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jathon-yang/go-wxsqlite3/9cecf6d69b21b08c250ed990606253af3bfc2672/go.sum -------------------------------------------------------------------------------- /sqlite3_context.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | package sqlite3 7 | 8 | /* 9 | 10 | #ifndef USE_LIBSQLITE3 11 | #include "sqlite3-binding.h" 12 | #else 13 | #include 14 | #endif 15 | #include 16 | // These wrappers are necessary because SQLITE_TRANSIENT 17 | // is a pointer constant, and cgo doesn't translate them correctly. 18 | 19 | static inline void my_result_text(sqlite3_context *ctx, char *p, int np) { 20 | sqlite3_result_text(ctx, p, np, SQLITE_TRANSIENT); 21 | } 22 | 23 | static inline void my_result_blob(sqlite3_context *ctx, void *p, int np) { 24 | sqlite3_result_blob(ctx, p, np, SQLITE_TRANSIENT); 25 | } 26 | */ 27 | import "C" 28 | 29 | import ( 30 | "math" 31 | "reflect" 32 | "unsafe" 33 | ) 34 | 35 | const i64 = unsafe.Sizeof(int(0)) > 4 36 | 37 | // SQLiteContext behave sqlite3_context 38 | type SQLiteContext C.sqlite3_context 39 | 40 | // ResultBool sets the result of an SQL function. 41 | func (c *SQLiteContext) ResultBool(b bool) { 42 | if b { 43 | c.ResultInt(1) 44 | } else { 45 | c.ResultInt(0) 46 | } 47 | } 48 | 49 | // ResultBlob sets the result of an SQL function. 50 | // See: sqlite3_result_blob, http://sqlite.org/c3ref/result_blob.html 51 | func (c *SQLiteContext) ResultBlob(b []byte) { 52 | if i64 && len(b) > math.MaxInt32 { 53 | C.sqlite3_result_error_toobig((*C.sqlite3_context)(c)) 54 | return 55 | } 56 | var p *byte 57 | if len(b) > 0 { 58 | p = &b[0] 59 | } 60 | C.my_result_blob((*C.sqlite3_context)(c), unsafe.Pointer(p), C.int(len(b))) 61 | } 62 | 63 | // ResultDouble sets the result of an SQL function. 64 | // See: sqlite3_result_double, http://sqlite.org/c3ref/result_blob.html 65 | func (c *SQLiteContext) ResultDouble(d float64) { 66 | C.sqlite3_result_double((*C.sqlite3_context)(c), C.double(d)) 67 | } 68 | 69 | // ResultInt sets the result of an SQL function. 70 | // See: sqlite3_result_int, http://sqlite.org/c3ref/result_blob.html 71 | func (c *SQLiteContext) ResultInt(i int) { 72 | if i64 && (i > math.MaxInt32 || i < math.MinInt32) { 73 | C.sqlite3_result_int64((*C.sqlite3_context)(c), C.sqlite3_int64(i)) 74 | } else { 75 | C.sqlite3_result_int((*C.sqlite3_context)(c), C.int(i)) 76 | } 77 | } 78 | 79 | // ResultInt64 sets the result of an SQL function. 80 | // See: sqlite3_result_int64, http://sqlite.org/c3ref/result_blob.html 81 | func (c *SQLiteContext) ResultInt64(i int64) { 82 | C.sqlite3_result_int64((*C.sqlite3_context)(c), C.sqlite3_int64(i)) 83 | } 84 | 85 | // ResultNull sets the result of an SQL function. 86 | // See: sqlite3_result_null, http://sqlite.org/c3ref/result_blob.html 87 | func (c *SQLiteContext) ResultNull() { 88 | C.sqlite3_result_null((*C.sqlite3_context)(c)) 89 | } 90 | 91 | // ResultText sets the result of an SQL function. 92 | // See: sqlite3_result_text, http://sqlite.org/c3ref/result_blob.html 93 | func (c *SQLiteContext) ResultText(s string) { 94 | h := (*reflect.StringHeader)(unsafe.Pointer(&s)) 95 | cs, l := (*C.char)(unsafe.Pointer(h.Data)), C.int(h.Len) 96 | C.my_result_text((*C.sqlite3_context)(c), cs, l) 97 | } 98 | 99 | // ResultZeroblob sets the result of an SQL function. 100 | // See: sqlite3_result_zeroblob, http://sqlite.org/c3ref/result_blob.html 101 | func (c *SQLiteContext) ResultZeroblob(n int) { 102 | C.sqlite3_result_zeroblob((*C.sqlite3_context)(c), C.int(n)) 103 | } 104 | -------------------------------------------------------------------------------- /sqlite3_func_crypt.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 G.J.R. Timmer . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | package sqlite3 7 | 8 | import ( 9 | "crypto/sha1" 10 | "crypto/sha256" 11 | "crypto/sha512" 12 | ) 13 | 14 | // This file provides several different implementations for the 15 | // default embedded sqlite_crypt function. 16 | // This function is uses a caesar-cypher by default 17 | // and is used within the UserAuthentication module to encode 18 | // the password. 19 | // 20 | // The provided functions can be used as an overload to the sqlite_crypt 21 | // function through the use of the RegisterFunc on the connection. 22 | // 23 | // Because the functions can serv a purpose to an end-user 24 | // without using the UserAuthentication module 25 | // the functions are default compiled in. 26 | // 27 | // From SQLITE3 - user-auth.txt 28 | // The sqlite_user.pw field is encoded by a built-in SQL function 29 | // "sqlite_crypt(X,Y)". The two arguments are both BLOBs. The first argument 30 | // is the plaintext password supplied to the sqlite3_user_authenticate() 31 | // interface. The second argument is the sqlite_user.pw value and is supplied 32 | // so that the function can extract the "salt" used by the password encoder. 33 | // The result of sqlite_crypt(X,Y) is another blob which is the value that 34 | // ends up being stored in sqlite_user.pw. To verify credentials X supplied 35 | // by the sqlite3_user_authenticate() routine, SQLite runs: 36 | // 37 | // sqlite_user.pw == sqlite_crypt(X, sqlite_user.pw) 38 | // 39 | // To compute an appropriate sqlite_user.pw value from a new or modified 40 | // password X, sqlite_crypt(X,NULL) is run. A new random salt is selected 41 | // when the second argument is NULL. 42 | // 43 | // The built-in version of of sqlite_crypt() uses a simple Caesar-cypher 44 | // which prevents passwords from being revealed by searching the raw database 45 | // for ASCII text, but is otherwise trivally broken. For better password 46 | // security, the database should be encrypted using the SQLite Encryption 47 | // Extension or similar technology. Or, the application can use the 48 | // sqlite3_create_function() interface to provide an alternative 49 | // implementation of sqlite_crypt() that computes a stronger password hash, 50 | // perhaps using a cryptographic hash function like SHA1. 51 | 52 | // CryptEncoderSHA1 encodes a password with SHA1 53 | func CryptEncoderSHA1(pass []byte, hash interface{}) []byte { 54 | h := sha1.Sum(pass) 55 | return h[:] 56 | } 57 | 58 | // CryptEncoderSSHA1 encodes a password with SHA1 with the 59 | // configured salt. 60 | func CryptEncoderSSHA1(salt string) func(pass []byte, hash interface{}) []byte { 61 | return func(pass []byte, hash interface{}) []byte { 62 | s := []byte(salt) 63 | p := append(pass, s...) 64 | h := sha1.Sum(p) 65 | return h[:] 66 | } 67 | } 68 | 69 | // CryptEncoderSHA256 encodes a password with SHA256 70 | func CryptEncoderSHA256(pass []byte, hash interface{}) []byte { 71 | h := sha256.Sum256(pass) 72 | return h[:] 73 | } 74 | 75 | // CryptEncoderSSHA256 encodes a password with SHA256 76 | // with the configured salt 77 | func CryptEncoderSSHA256(salt string) func(pass []byte, hash interface{}) []byte { 78 | return func(pass []byte, hash interface{}) []byte { 79 | s := []byte(salt) 80 | p := append(pass, s...) 81 | h := sha256.Sum256(p) 82 | return h[:] 83 | } 84 | } 85 | 86 | // CryptEncoderSHA384 encodes a password with SHA384 87 | func CryptEncoderSHA384(pass []byte, hash interface{}) []byte { 88 | h := sha512.Sum384(pass) 89 | return h[:] 90 | } 91 | 92 | // CryptEncoderSSHA384 encodes a password with SHA384 93 | // with the configured salt 94 | func CryptEncoderSSHA384(salt string) func(pass []byte, hash interface{}) []byte { 95 | return func(pass []byte, hash interface{}) []byte { 96 | s := []byte(salt) 97 | p := append(pass, s...) 98 | h := sha512.Sum384(p) 99 | return h[:] 100 | } 101 | } 102 | 103 | // CryptEncoderSHA512 encodes a password with SHA512 104 | func CryptEncoderSHA512(pass []byte, hash interface{}) []byte { 105 | h := sha512.Sum512(pass) 106 | return h[:] 107 | } 108 | 109 | // CryptEncoderSSHA512 encodes a password with SHA512 110 | // with the configured salt 111 | func CryptEncoderSSHA512(salt string) func(pass []byte, hash interface{}) []byte { 112 | return func(pass []byte, hash interface{}) []byte { 113 | s := []byte(salt) 114 | p := append(pass, s...) 115 | h := sha512.Sum512(p) 116 | return h[:] 117 | } 118 | } 119 | 120 | // EOF 121 | -------------------------------------------------------------------------------- /sqlite3_func_crypt_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 G.J.R. Timmer . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | package sqlite3 7 | 8 | import ( 9 | "fmt" 10 | "strings" 11 | "testing" 12 | ) 13 | 14 | // TestCryptEncoders to increase coverage 15 | func TestCryptEncoders(t *testing.T) { 16 | tests := []struct { 17 | enc string 18 | salt string 19 | expected string 20 | }{ 21 | {"sha1", "", "d033e22ae348aeb5660fc2140aec35850c4da997"}, 22 | {"sha256", "", "8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918"}, 23 | {"sha384", "", "9ca694a90285c034432c9550421b7b9dbd5c0f4b6673f05f6dbce58052ba20e4248041956ee8c9a2ec9f10290cdc0782"}, 24 | {"sha512", "", "c7ad44cbad762a5da0a452f9e854fdc1e0e7a52a38015f23f3eab1d80b931dd472634dfac71cd34ebc35d16ab7fb8a90c81f975113d6c7538dc69dd8de9077ec"}, 25 | {"ssha1", "salt", "9bc7aa55f08fdad935c3f8362d3f48bcf70eb280"}, 26 | {"ssha256", "salt", "f9a81477552594c79f2abc3fc099daa896a6e3a3590a55ffa392b6000412e80b"}, 27 | {"ssha384", "salt", "9ed776b477fcfc1b5e584989e8d770f5e17d98a7643546a63c2b07d4ab00f1348f6b8e73103d3a23554f727136e8c215"}, 28 | {"ssha512", "salt", "3c4a79782143337be4492be072abcfe979dd703c00541a8c39a0f3df4bab2029c050cf46fddc47090b5b04ac537b3e78189e3de16e601e859f95c51ac9f6dafb"}, 29 | } 30 | 31 | for _, e := range tests { 32 | var fn func(pass []byte, hash interface{}) []byte 33 | switch e.enc { 34 | case "sha1": 35 | fn = CryptEncoderSHA1 36 | case "ssha1": 37 | fn = CryptEncoderSSHA1(e.salt) 38 | case "sha256": 39 | fn = CryptEncoderSHA256 40 | case "ssha256": 41 | fn = CryptEncoderSSHA256(e.salt) 42 | case "sha384": 43 | fn = CryptEncoderSHA384 44 | case "ssha384": 45 | fn = CryptEncoderSSHA384(e.salt) 46 | case "sha512": 47 | fn = CryptEncoderSHA512 48 | case "ssha512": 49 | fn = CryptEncoderSSHA512(e.salt) 50 | } 51 | 52 | h := fn([]byte("admin"), nil) 53 | if strings.Compare(fmt.Sprintf("%x", h), e.expected) != 0 { 54 | t.Fatalf("Invalid %s hash: expected: %s; got: %x", strings.ToUpper(e.enc), e.expected, h) 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /sqlite3_go113_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // +build go1.13,cgo 7 | 8 | package sqlite3 9 | 10 | import ( 11 | "context" 12 | "database/sql" 13 | "database/sql/driver" 14 | "errors" 15 | "os" 16 | "testing" 17 | ) 18 | 19 | func TestBeginTxCancel(t *testing.T) { 20 | srcTempFilename := TempFilename(t) 21 | defer os.Remove(srcTempFilename) 22 | 23 | db, err := sql.Open("sqlite3", srcTempFilename) 24 | if err != nil { 25 | t.Fatal(err) 26 | } 27 | 28 | db.SetMaxOpenConns(10) 29 | db.SetMaxIdleConns(5) 30 | 31 | defer db.Close() 32 | initDatabase(t, db, 100) 33 | 34 | // create several go-routines to expose racy issue 35 | for i := 0; i < 1000; i++ { 36 | func() { 37 | ctx, cancel := context.WithCancel(context.Background()) 38 | conn, err := db.Conn(ctx) 39 | if err != nil { 40 | t.Fatal(err) 41 | } 42 | defer func() { 43 | if err := conn.Close(); err != nil { 44 | t.Error(err) 45 | } 46 | }() 47 | 48 | err = conn.Raw(func(driverConn interface{}) error { 49 | d, ok := driverConn.(driver.ConnBeginTx) 50 | if !ok { 51 | t.Fatal("unexpected: wrong type") 52 | } 53 | // checks that conn.Raw can be used to get *SQLiteConn 54 | if _, ok = driverConn.(*SQLiteConn); !ok { 55 | t.Fatalf("conn.Raw() driverConn type=%T, expected *SQLiteConn", driverConn) 56 | } 57 | 58 | go cancel() // make it cancel concurrently with exec("BEGIN"); 59 | tx, err := d.BeginTx(ctx, driver.TxOptions{}) 60 | switch err { 61 | case nil: 62 | switch err := tx.Rollback(); err { 63 | case nil, sql.ErrTxDone: 64 | default: 65 | return err 66 | } 67 | case context.Canceled: 68 | default: 69 | // must not fail with "cannot start a transaction within a transaction" 70 | return err 71 | } 72 | return nil 73 | }) 74 | if err != nil { 75 | t.Fatal(err) 76 | } 77 | }() 78 | } 79 | } 80 | 81 | func TestStmtReadonly(t *testing.T) { 82 | db, err := sql.Open("sqlite3", ":memory:") 83 | if err != nil { 84 | t.Fatal(err) 85 | } 86 | 87 | _, err = db.Exec("CREATE TABLE t (count INT)") 88 | if err != nil { 89 | t.Fatal(err) 90 | } 91 | 92 | isRO := func(query string) bool { 93 | c, err := db.Conn(context.Background()) 94 | if err != nil { 95 | return false 96 | } 97 | 98 | var ro bool 99 | c.Raw(func(dc interface{}) error { 100 | stmt, err := dc.(*SQLiteConn).Prepare(query) 101 | if err != nil { 102 | return err 103 | } 104 | if stmt == nil { 105 | return errors.New("stmt is nil") 106 | } 107 | ro = stmt.(*SQLiteStmt).Readonly() 108 | return nil 109 | }) 110 | return ro // On errors ro will remain false. 111 | } 112 | 113 | if !isRO(`select * from t`) { 114 | t.Error("select not seen as read-only") 115 | } 116 | if isRO(`insert into t values (1), (2)`) { 117 | t.Error("insert seen as read-only") 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /sqlite3_go18.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // +build cgo 7 | // +build go1.8 8 | 9 | package sqlite3 10 | 11 | import ( 12 | "database/sql/driver" 13 | 14 | "context" 15 | ) 16 | 17 | // Ping implement Pinger. 18 | func (c *SQLiteConn) Ping(ctx context.Context) error { 19 | if c.db == nil { 20 | // must be ErrBadConn for sql to close the database 21 | return driver.ErrBadConn 22 | } 23 | return nil 24 | } 25 | 26 | // QueryContext implement QueryerContext. 27 | func (c *SQLiteConn) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) { 28 | list := make([]namedValue, len(args)) 29 | for i, nv := range args { 30 | list[i] = namedValue(nv) 31 | } 32 | return c.query(ctx, query, list) 33 | } 34 | 35 | // ExecContext implement ExecerContext. 36 | func (c *SQLiteConn) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) { 37 | list := make([]namedValue, len(args)) 38 | for i, nv := range args { 39 | list[i] = namedValue(nv) 40 | } 41 | return c.exec(ctx, query, list) 42 | } 43 | 44 | // PrepareContext implement ConnPrepareContext. 45 | func (c *SQLiteConn) PrepareContext(ctx context.Context, query string) (driver.Stmt, error) { 46 | return c.prepare(ctx, query) 47 | } 48 | 49 | // BeginTx implement ConnBeginTx. 50 | func (c *SQLiteConn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) { 51 | return c.begin(ctx) 52 | } 53 | 54 | // QueryContext implement QueryerContext. 55 | func (s *SQLiteStmt) QueryContext(ctx context.Context, args []driver.NamedValue) (driver.Rows, error) { 56 | list := make([]namedValue, len(args)) 57 | for i, nv := range args { 58 | list[i] = namedValue(nv) 59 | } 60 | return s.query(ctx, list) 61 | } 62 | 63 | // ExecContext implement ExecerContext. 64 | func (s *SQLiteStmt) ExecContext(ctx context.Context, args []driver.NamedValue) (driver.Result, error) { 65 | list := make([]namedValue, len(args)) 66 | for i, nv := range args { 67 | list[i] = namedValue(nv) 68 | } 69 | return s.exec(ctx, list) 70 | } 71 | -------------------------------------------------------------------------------- /sqlite3_libsqlite3.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // +build libsqlite3 7 | 8 | package sqlite3 9 | 10 | /* 11 | #cgo CFLAGS: -DUSE_LIBSQLITE3 12 | #cgo linux LDFLAGS: -lsqlite3 13 | #cgo darwin LDFLAGS: -L/usr/local/opt/sqlite/lib -lsqlite3 14 | #cgo darwin CFLAGS: -I/usr/local/opt/sqlite/include 15 | #cgo openbsd LDFLAGS: -lsqlite3 16 | #cgo solaris LDFLAGS: -lsqlite3 17 | #cgo windows LDFLAGS: -lsqlite3 18 | */ 19 | import "C" 20 | -------------------------------------------------------------------------------- /sqlite3_load_extension.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // +build !sqlite_omit_load_extension 7 | 8 | package sqlite3 9 | 10 | /* 11 | #ifndef USE_LIBSQLITE3 12 | #include "sqlite3-binding.h" 13 | #else 14 | #include 15 | #endif 16 | #include 17 | */ 18 | import "C" 19 | import ( 20 | "errors" 21 | "unsafe" 22 | ) 23 | 24 | func (c *SQLiteConn) loadExtensions(extensions []string) error { 25 | rv := C.sqlite3_enable_load_extension(c.db, 1) 26 | if rv != C.SQLITE_OK { 27 | return errors.New(C.GoString(C.sqlite3_errmsg(c.db))) 28 | } 29 | 30 | for _, extension := range extensions { 31 | if err := c.loadExtension(extension, nil); err != nil { 32 | C.sqlite3_enable_load_extension(c.db, 0) 33 | return err 34 | } 35 | } 36 | 37 | rv = C.sqlite3_enable_load_extension(c.db, 0) 38 | if rv != C.SQLITE_OK { 39 | return errors.New(C.GoString(C.sqlite3_errmsg(c.db))) 40 | } 41 | 42 | return nil 43 | } 44 | 45 | // LoadExtension load the sqlite3 extension. 46 | func (c *SQLiteConn) LoadExtension(lib string, entry string) error { 47 | rv := C.sqlite3_enable_load_extension(c.db, 1) 48 | if rv != C.SQLITE_OK { 49 | return errors.New(C.GoString(C.sqlite3_errmsg(c.db))) 50 | } 51 | 52 | if err := c.loadExtension(lib, &entry); err != nil { 53 | C.sqlite3_enable_load_extension(c.db, 0) 54 | return err 55 | } 56 | 57 | rv = C.sqlite3_enable_load_extension(c.db, 0) 58 | if rv != C.SQLITE_OK { 59 | return errors.New(C.GoString(C.sqlite3_errmsg(c.db))) 60 | } 61 | 62 | return nil 63 | } 64 | 65 | func (c *SQLiteConn) loadExtension(lib string, entry *string) error { 66 | clib := C.CString(lib) 67 | defer C.free(unsafe.Pointer(clib)) 68 | 69 | var centry *C.char 70 | if entry != nil { 71 | centry = C.CString(*entry) 72 | defer C.free(unsafe.Pointer(centry)) 73 | } 74 | 75 | var errMsg *C.char 76 | defer C.sqlite3_free(unsafe.Pointer(errMsg)) 77 | 78 | rv := C.sqlite3_load_extension(c.db, clib, centry, &errMsg) 79 | if rv != C.SQLITE_OK { 80 | return errors.New(C.GoString(errMsg)) 81 | } 82 | 83 | return nil 84 | } 85 | -------------------------------------------------------------------------------- /sqlite3_load_extension_omit.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // +build sqlite_omit_load_extension 7 | 8 | package sqlite3 9 | 10 | /* 11 | #cgo CFLAGS: -DSQLITE_OMIT_LOAD_EXTENSION 12 | */ 13 | import "C" 14 | import ( 15 | "errors" 16 | ) 17 | 18 | func (c *SQLiteConn) loadExtensions(extensions []string) error { 19 | return errors.New("Extensions have been disabled for static builds") 20 | } 21 | 22 | func (c *SQLiteConn) LoadExtension(lib string, entry string) error { 23 | return errors.New("Extensions have been disabled for static builds") 24 | } 25 | -------------------------------------------------------------------------------- /sqlite3_load_extension_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // +build !sqlite_omit_load_extension 7 | 8 | package sqlite3 9 | 10 | import ( 11 | "database/sql" 12 | "testing" 13 | ) 14 | 15 | func TestExtensionsError(t *testing.T) { 16 | sql.Register("sqlite3_TestExtensionsError", 17 | &SQLiteDriver{ 18 | Extensions: []string{ 19 | "foobar", 20 | }, 21 | }, 22 | ) 23 | 24 | db, err := sql.Open("sqlite3_TestExtensionsError", ":memory:") 25 | if err != nil { 26 | t.Fatal(err) 27 | } 28 | defer db.Close() 29 | 30 | err = db.Ping() 31 | if err == nil { 32 | t.Fatal("expected error loading non-existent extension") 33 | } 34 | 35 | if err.Error() == "not an error" { 36 | t.Fatal("expected error from sqlite3_enable_load_extension to be returned") 37 | } 38 | } 39 | 40 | func TestLoadExtensionError(t *testing.T) { 41 | sql.Register("sqlite3_TestLoadExtensionError", 42 | &SQLiteDriver{ 43 | ConnectHook: func(c *SQLiteConn) error { 44 | return c.LoadExtension("foobar", "") 45 | }, 46 | }, 47 | ) 48 | 49 | db, err := sql.Open("sqlite3_TestLoadExtensionError", ":memory:") 50 | if err != nil { 51 | t.Fatal(err) 52 | } 53 | defer db.Close() 54 | 55 | err = db.Ping() 56 | if err == nil { 57 | t.Fatal("expected error loading non-existent extension") 58 | } 59 | 60 | if err.Error() == "not an error" { 61 | t.Fatal("expected error from sqlite3_enable_load_extension to be returned") 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /sqlite3_opt_allow_uri_authority.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 Yasuhiro Matsumoto . 2 | // Copyright (C) 2018 G.J.R. Timmer . 3 | // 4 | // Use of this source code is governed by an MIT-style 5 | // license that can be found in the LICENSE file. 6 | 7 | // +build sqlite_allow_uri_authority 8 | 9 | package sqlite3 10 | 11 | /* 12 | #cgo CFLAGS: -DSQLITE_ALLOW_URI_AUTHORITY 13 | #cgo LDFLAGS: -lm 14 | */ 15 | import "C" 16 | -------------------------------------------------------------------------------- /sqlite3_opt_app_armor.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 Yasuhiro Matsumoto . 2 | // Copyright (C) 2018 G.J.R. Timmer . 3 | // 4 | // Use of this source code is governed by an MIT-style 5 | // license that can be found in the LICENSE file. 6 | 7 | // +build !windows 8 | // +build sqlite_app_armor 9 | 10 | package sqlite3 11 | 12 | /* 13 | #cgo CFLAGS: -DSQLITE_ENABLE_API_ARMOR 14 | #cgo LDFLAGS: -lm 15 | */ 16 | import "C" 17 | -------------------------------------------------------------------------------- /sqlite3_opt_column_metadata.go: -------------------------------------------------------------------------------- 1 | // +build sqlite_column_metadata 2 | 3 | package sqlite3 4 | 5 | /* 6 | #ifndef USE_LIBSQLITE3 7 | #cgo CFLAGS: -DSQLITE_ENABLE_COLUMN_METADATA 8 | #include 9 | #else 10 | #include 11 | #endif 12 | */ 13 | import "C" 14 | 15 | // ColumnTableName returns the table that is the origin of a particular result 16 | // column in a SELECT statement. 17 | // 18 | // See https://www.sqlite.org/c3ref/column_database_name.html 19 | func (s *SQLiteStmt) ColumnTableName(n int) string { 20 | return C.GoString(C.sqlite3_column_table_name(s.s, C.int(n))) 21 | } 22 | -------------------------------------------------------------------------------- /sqlite3_opt_column_metadata_test.go: -------------------------------------------------------------------------------- 1 | // +build sqlite_column_metadata 2 | 3 | package sqlite3 4 | 5 | import "testing" 6 | 7 | func TestColumnTableName(t *testing.T) { 8 | d := SQLiteDriver{} 9 | conn, err := d.Open(":memory:") 10 | if err != nil { 11 | t.Fatal("failed to get database connection:", err) 12 | } 13 | defer conn.Close() 14 | sqlite3conn := conn.(*SQLiteConn) 15 | 16 | _, err = sqlite3conn.Exec(`CREATE TABLE foo (name string)`, nil) 17 | if err != nil { 18 | t.Fatal("Failed to create table:", err) 19 | } 20 | _, err = sqlite3conn.Exec(`CREATE TABLE bar (name string)`, nil) 21 | if err != nil { 22 | t.Fatal("Failed to create table:", err) 23 | } 24 | 25 | stmt, err := sqlite3conn.Prepare(`SELECT * FROM foo JOIN bar ON foo.name = bar.name`) 26 | if err != nil { 27 | t.Fatal(err) 28 | } 29 | 30 | if exp, got := "foo", stmt.(*SQLiteStmt).ColumnTableName(0); exp != got { 31 | t.Fatalf("Incorrect table name returned expected: %s, got: %s", exp, got) 32 | } 33 | if exp, got := "bar", stmt.(*SQLiteStmt).ColumnTableName(1); exp != got { 34 | t.Fatalf("Incorrect table name returned expected: %s, got: %s", exp, got) 35 | } 36 | if exp, got := "", stmt.(*SQLiteStmt).ColumnTableName(2); exp != got { 37 | t.Fatalf("Incorrect table name returned expected: %s, got: %s", exp, got) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /sqlite3_opt_foreign_keys.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 Yasuhiro Matsumoto . 2 | // Copyright (C) 2018 G.J.R. Timmer . 3 | // 4 | // Use of this source code is governed by an MIT-style 5 | // license that can be found in the LICENSE file. 6 | 7 | // +build sqlite_foreign_keys 8 | 9 | package sqlite3 10 | 11 | /* 12 | #cgo CFLAGS: -DSQLITE_DEFAULT_FOREIGN_KEYS=1 13 | #cgo LDFLAGS: -lm 14 | */ 15 | import "C" 16 | -------------------------------------------------------------------------------- /sqlite3_opt_fts3_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // +build cgo 7 | 8 | package sqlite3 9 | 10 | import ( 11 | "database/sql" 12 | "os" 13 | "testing" 14 | ) 15 | 16 | func TestFTS3(t *testing.T) { 17 | tempFilename := TempFilename(t) 18 | defer os.Remove(tempFilename) 19 | db, err := sql.Open("sqlite3", tempFilename) 20 | if err != nil { 21 | t.Fatal("Failed to open database:", err) 22 | } 23 | defer db.Close() 24 | 25 | _, err = db.Exec("DROP TABLE foo") 26 | _, err = db.Exec("CREATE VIRTUAL TABLE foo USING fts3(id INTEGER PRIMARY KEY, value TEXT)") 27 | if err != nil { 28 | t.Fatal("Failed to create table:", err) 29 | } 30 | 31 | _, err = db.Exec("INSERT INTO foo(id, value) VALUES(?, ?)", 1, `今日の 晩御飯は 天麩羅よ`) 32 | if err != nil { 33 | t.Fatal("Failed to insert value:", err) 34 | } 35 | 36 | _, err = db.Exec("INSERT INTO foo(id, value) VALUES(?, ?)", 2, `今日は いい 天気だ`) 37 | if err != nil { 38 | t.Fatal("Failed to insert value:", err) 39 | } 40 | 41 | rows, err := db.Query("SELECT id, value FROM foo WHERE value MATCH '今日* 天*'") 42 | if err != nil { 43 | t.Fatal("Unable to query foo table:", err) 44 | } 45 | defer rows.Close() 46 | 47 | for rows.Next() { 48 | var id int 49 | var value string 50 | 51 | if err := rows.Scan(&id, &value); err != nil { 52 | t.Error("Unable to scan results:", err) 53 | continue 54 | } 55 | 56 | if id == 1 && value != `今日の 晩御飯は 天麩羅よ` { 57 | t.Error("Value for id 1 should be `今日の 晩御飯は 天麩羅よ`, but:", value) 58 | } else if id == 2 && value != `今日は いい 天気だ` { 59 | t.Error("Value for id 2 should be `今日は いい 天気だ`, but:", value) 60 | } 61 | } 62 | 63 | rows, err = db.Query("SELECT value FROM foo WHERE value MATCH '今日* 天麩羅*'") 64 | if err != nil { 65 | t.Fatal("Unable to query foo table:", err) 66 | } 67 | defer rows.Close() 68 | 69 | var value string 70 | if !rows.Next() { 71 | t.Fatal("Result should be only one") 72 | } 73 | 74 | if err := rows.Scan(&value); err != nil { 75 | t.Fatal("Unable to scan results:", err) 76 | } 77 | 78 | if value != `今日の 晩御飯は 天麩羅よ` { 79 | t.Fatal("Value should be `今日の 晩御飯は 天麩羅よ`, but:", value) 80 | } 81 | 82 | if rows.Next() { 83 | t.Fatal("Result should be only one") 84 | } 85 | } 86 | 87 | func TestFTS4(t *testing.T) { 88 | tempFilename := TempFilename(t) 89 | defer os.Remove(tempFilename) 90 | db, err := sql.Open("sqlite3", tempFilename) 91 | if err != nil { 92 | t.Fatal("Failed to open database:", err) 93 | } 94 | defer db.Close() 95 | 96 | _, err = db.Exec("DROP TABLE foo") 97 | _, err = db.Exec("CREATE VIRTUAL TABLE foo USING fts4(tokenize=unicode61, id INTEGER PRIMARY KEY, value TEXT)") 98 | switch { 99 | case err != nil && err.Error() == "unknown tokenizer: unicode61": 100 | t.Skip("FTS4 not supported") 101 | case err != nil: 102 | t.Fatal("Failed to create table:", err) 103 | } 104 | 105 | _, err = db.Exec("INSERT INTO foo(id, value) VALUES(?, ?)", 1, `février`) 106 | if err != nil { 107 | t.Fatal("Failed to insert value:", err) 108 | } 109 | 110 | rows, err := db.Query("SELECT value FROM foo WHERE value MATCH 'fevrier'") 111 | if err != nil { 112 | t.Fatal("Unable to query foo table:", err) 113 | } 114 | defer rows.Close() 115 | 116 | var value string 117 | if !rows.Next() { 118 | t.Fatal("Result should be only one") 119 | } 120 | 121 | if err := rows.Scan(&value); err != nil { 122 | t.Fatal("Unable to scan results:", err) 123 | } 124 | 125 | if value != `février` { 126 | t.Fatal("Value should be `février`, but:", value) 127 | } 128 | 129 | if rows.Next() { 130 | t.Fatal("Result should be only one") 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /sqlite3_opt_fts5.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // +build sqlite_fts5 fts5 7 | 8 | package sqlite3 9 | 10 | /* 11 | #cgo CFLAGS: -DSQLITE_ENABLE_FTS5 12 | #cgo LDFLAGS: -lm 13 | */ 14 | import "C" 15 | -------------------------------------------------------------------------------- /sqlite3_opt_icu.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // +build sqlite_icu icu 7 | 8 | package sqlite3 9 | 10 | /* 11 | #cgo LDFLAGS: -licuuc -licui18n 12 | #cgo CFLAGS: -DSQLITE_ENABLE_ICU 13 | #cgo darwin CFLAGS: -I/usr/local/opt/icu4c/include 14 | #cgo darwin LDFLAGS: -L/usr/local/opt/icu4c/lib 15 | #cgo openbsd LDFLAGS: -lsqlite3 16 | */ 17 | import "C" 18 | -------------------------------------------------------------------------------- /sqlite3_opt_introspect.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 Yasuhiro Matsumoto . 2 | // Copyright (C) 2018 G.J.R. Timmer . 3 | 4 | // Use of this source code is governed by an MIT-style 5 | // license that can be found in the LICENSE file. 6 | 7 | // +build sqlite_introspect 8 | 9 | package sqlite3 10 | 11 | /* 12 | #cgo CFLAGS: -DSQLITE_INTROSPECTION_PRAGMAS 13 | #cgo LDFLAGS: -lm 14 | */ 15 | import "C" 16 | -------------------------------------------------------------------------------- /sqlite3_opt_json1.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // +build sqlite_json sqlite_json1 json1 7 | 8 | package sqlite3 9 | 10 | /* 11 | #cgo CFLAGS: -DSQLITE_ENABLE_JSON1 12 | */ 13 | import "C" 14 | -------------------------------------------------------------------------------- /sqlite3_opt_preupdate.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 G.J.R. Timmer . 2 | // Copyright (C) 2018 segment.com 3 | // 4 | // Use of this source code is governed by an MIT-style 5 | // license that can be found in the LICENSE file. 6 | 7 | // +build cgo 8 | 9 | package sqlite3 10 | 11 | // SQLitePreUpdateData represents all of the data available during a 12 | // pre-update hook call. 13 | type SQLitePreUpdateData struct { 14 | Conn *SQLiteConn 15 | Op int 16 | DatabaseName string 17 | TableName string 18 | OldRowID int64 19 | NewRowID int64 20 | } 21 | -------------------------------------------------------------------------------- /sqlite3_opt_preupdate_hook.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 G.J.R. Timmer . 2 | // Copyright (C) 2018 segment.com 3 | // 4 | // Use of this source code is governed by an MIT-style 5 | // license that can be found in the LICENSE file. 6 | 7 | // +build sqlite_preupdate_hook 8 | 9 | package sqlite3 10 | 11 | /* 12 | #cgo CFLAGS: -DSQLITE_ENABLE_PREUPDATE_HOOK 13 | #cgo LDFLAGS: -lm 14 | 15 | #ifndef USE_LIBSQLITE3 16 | #include "sqlite3-binding.h" 17 | #else 18 | #include 19 | #endif 20 | #include 21 | #include 22 | 23 | void preUpdateHookTrampoline(void*, sqlite3 *, int, char *, char *, sqlite3_int64, sqlite3_int64); 24 | */ 25 | import "C" 26 | import ( 27 | "errors" 28 | "unsafe" 29 | ) 30 | 31 | // RegisterPreUpdateHook sets the pre-update hook for a connection. 32 | // 33 | // The callback is passed a SQLitePreUpdateData struct with the data for 34 | // the update, as well as methods for fetching copies of impacted data. 35 | // 36 | // If there is an existing update hook for this connection, it will be 37 | // removed. If callback is nil the existing hook (if any) will be removed 38 | // without creating a new one. 39 | func (c *SQLiteConn) RegisterPreUpdateHook(callback func(SQLitePreUpdateData)) { 40 | if callback == nil { 41 | C.sqlite3_preupdate_hook(c.db, nil, nil) 42 | } else { 43 | C.sqlite3_preupdate_hook(c.db, (*[0]byte)(unsafe.Pointer(C.preUpdateHookTrampoline)), unsafe.Pointer(newHandle(c, callback))) 44 | } 45 | } 46 | 47 | // Depth returns the source path of the write, see sqlite3_preupdate_depth() 48 | func (d *SQLitePreUpdateData) Depth() int { 49 | return int(C.sqlite3_preupdate_depth(d.Conn.db)) 50 | } 51 | 52 | // Count returns the number of columns in the row 53 | func (d *SQLitePreUpdateData) Count() int { 54 | return int(C.sqlite3_preupdate_count(d.Conn.db)) 55 | } 56 | 57 | func (d *SQLitePreUpdateData) row(dest []interface{}, new bool) error { 58 | for i := 0; i < d.Count() && i < len(dest); i++ { 59 | var val *C.sqlite3_value 60 | var src interface{} 61 | 62 | // Initially I tried making this just a function pointer argument, but 63 | // it's absurdly complicated to pass C function pointers. 64 | if new { 65 | C.sqlite3_preupdate_new(d.Conn.db, C.int(i), &val) 66 | } else { 67 | C.sqlite3_preupdate_old(d.Conn.db, C.int(i), &val) 68 | } 69 | 70 | switch C.sqlite3_value_type(val) { 71 | case C.SQLITE_INTEGER: 72 | src = int64(C.sqlite3_value_int64(val)) 73 | case C.SQLITE_FLOAT: 74 | src = float64(C.sqlite3_value_double(val)) 75 | case C.SQLITE_BLOB: 76 | len := C.sqlite3_value_bytes(val) 77 | blobptr := C.sqlite3_value_blob(val) 78 | src = C.GoBytes(blobptr, len) 79 | case C.SQLITE_TEXT: 80 | len := C.sqlite3_value_bytes(val) 81 | cstrptr := unsafe.Pointer(C.sqlite3_value_text(val)) 82 | src = C.GoBytes(cstrptr, len) 83 | case C.SQLITE_NULL: 84 | src = nil 85 | } 86 | 87 | err := convertAssign(&dest[i], src) 88 | if err != nil { 89 | return err 90 | } 91 | } 92 | 93 | return nil 94 | } 95 | 96 | // Old populates dest with the row data to be replaced. This works similar to 97 | // database/sql's Rows.Scan() 98 | func (d *SQLitePreUpdateData) Old(dest ...interface{}) error { 99 | if d.Op == SQLITE_INSERT { 100 | return errors.New("There is no old row for INSERT operations") 101 | } 102 | return d.row(dest, false) 103 | } 104 | 105 | // New populates dest with the replacement row data. This works similar to 106 | // database/sql's Rows.Scan() 107 | func (d *SQLitePreUpdateData) New(dest ...interface{}) error { 108 | if d.Op == SQLITE_DELETE { 109 | return errors.New("There is no new row for DELETE operations") 110 | } 111 | return d.row(dest, true) 112 | } 113 | -------------------------------------------------------------------------------- /sqlite3_opt_preupdate_hook_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 G.J.R. Timmer . 2 | // Copyright (C) 2018 segment.com 3 | // 4 | // Use of this source code is governed by an MIT-style 5 | // license that can be found in the LICENSE file. 6 | 7 | // +build sqlite_preupdate_hook 8 | 9 | package sqlite3 10 | 11 | import ( 12 | "database/sql" 13 | "testing" 14 | ) 15 | 16 | type preUpdateHookDataForTest struct { 17 | databaseName string 18 | tableName string 19 | count int 20 | op int 21 | oldRow []interface{} 22 | newRow []interface{} 23 | } 24 | 25 | func TestPreUpdateHook(t *testing.T) { 26 | var events []preUpdateHookDataForTest 27 | 28 | sql.Register("sqlite3_PreUpdateHook", &SQLiteDriver{ 29 | ConnectHook: func(conn *SQLiteConn) error { 30 | conn.RegisterPreUpdateHook(func(data SQLitePreUpdateData) { 31 | eval := -1 32 | oldRow := []interface{}{eval} 33 | if data.Op != SQLITE_INSERT { 34 | err := data.Old(oldRow...) 35 | if err != nil { 36 | t.Fatalf("Unexpected error calling SQLitePreUpdateData.Old: %v", err) 37 | } 38 | } 39 | 40 | eval2 := -1 41 | newRow := []interface{}{eval2} 42 | if data.Op != SQLITE_DELETE { 43 | err := data.New(newRow...) 44 | if err != nil { 45 | t.Fatalf("Unexpected error calling SQLitePreUpdateData.New: %v", err) 46 | } 47 | } 48 | 49 | // tests dest bound checks in loop 50 | var tooSmallRow []interface{} 51 | if data.Op != SQLITE_INSERT { 52 | err := data.Old(tooSmallRow...) 53 | if err != nil { 54 | t.Fatalf("Unexpected error calling SQLitePreUpdateData.Old: %v", err) 55 | } 56 | if len(tooSmallRow) != 0 { 57 | t.Errorf("Expected tooSmallRow to be empty, got: %v", tooSmallRow) 58 | } 59 | } 60 | 61 | events = append(events, preUpdateHookDataForTest{ 62 | databaseName: data.DatabaseName, 63 | tableName: data.TableName, 64 | count: data.Count(), 65 | op: data.Op, 66 | oldRow: oldRow, 67 | newRow: newRow, 68 | }) 69 | }) 70 | return nil 71 | }, 72 | }) 73 | 74 | db, err := sql.Open("sqlite3_PreUpdateHook", ":memory:") 75 | if err != nil { 76 | t.Fatal("Failed to open database:", err) 77 | } 78 | defer db.Close() 79 | 80 | statements := []string{ 81 | "create table foo (id integer primary key)", 82 | "insert into foo values (9)", 83 | "update foo set id = 99 where id = 9", 84 | "delete from foo where id = 99", 85 | } 86 | for _, statement := range statements { 87 | _, err = db.Exec(statement) 88 | if err != nil { 89 | t.Fatalf("Unable to prepare test data [%v]: %v", statement, err) 90 | } 91 | } 92 | 93 | if len(events) != 3 { 94 | t.Errorf("Events should be 3 entries, got: %d", len(events)) 95 | } 96 | 97 | if events[0].op != SQLITE_INSERT { 98 | t.Errorf("Op isn't as expected: %v", events[0].op) 99 | } 100 | 101 | if events[1].op != SQLITE_UPDATE { 102 | t.Errorf("Op isn't as expected: %v", events[1].op) 103 | } 104 | 105 | if events[1].count != 1 { 106 | t.Errorf("Expected event row 1 to have 1 column, had: %v", events[1].count) 107 | } 108 | 109 | newRow_0_0 := events[0].newRow[0].(int64) 110 | if newRow_0_0 != 9 { 111 | t.Errorf("Expected event row 0 new column 0 to be == 9, got: %v", newRow_0_0) 112 | } 113 | 114 | oldRow_1_0 := events[1].oldRow[0].(int64) 115 | if oldRow_1_0 != 9 { 116 | t.Errorf("Expected event row 1 old column 0 to be == 9, got: %v", oldRow_1_0) 117 | } 118 | 119 | newRow_1_0 := events[1].newRow[0].(int64) 120 | if newRow_1_0 != 99 { 121 | t.Errorf("Expected event row 1 new column 0 to be == 99, got: %v", newRow_1_0) 122 | } 123 | 124 | oldRow_2_0 := events[2].oldRow[0].(int64) 125 | if oldRow_2_0 != 99 { 126 | t.Errorf("Expected event row 1 new column 0 to be == 99, got: %v", oldRow_2_0) 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /sqlite3_opt_preupdate_omit.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 G.J.R. Timmer . 2 | // Copyright (C) 2018 segment.com 3 | // 4 | // Use of this source code is governed by an MIT-style 5 | // license that can be found in the LICENSE file. 6 | 7 | // +build !sqlite_preupdate_hook,cgo 8 | 9 | package sqlite3 10 | 11 | // RegisterPreUpdateHook sets the pre-update hook for a connection. 12 | // 13 | // The callback is passed a SQLitePreUpdateData struct with the data for 14 | // the update, as well as methods for fetching copies of impacted data. 15 | // 16 | // If there is an existing update hook for this connection, it will be 17 | // removed. If callback is nil the existing hook (if any) will be removed 18 | // without creating a new one. 19 | func (c *SQLiteConn) RegisterPreUpdateHook(callback func(SQLitePreUpdateData)) { 20 | // NOOP 21 | } 22 | -------------------------------------------------------------------------------- /sqlite3_opt_secure_delete.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 Yasuhiro Matsumoto . 2 | // Copyright (C) 2018 G.J.R. Timmer . 3 | // 4 | // Use of this source code is governed by an MIT-style 5 | // license that can be found in the LICENSE file. 6 | 7 | // +build sqlite_secure_delete 8 | 9 | package sqlite3 10 | 11 | /* 12 | #cgo CFLAGS: -DSQLITE_SECURE_DELETE=1 13 | #cgo LDFLAGS: -lm 14 | */ 15 | import "C" 16 | -------------------------------------------------------------------------------- /sqlite3_opt_secure_delete_fast.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 Yasuhiro Matsumoto . 2 | // Copyright (C) 2018 G.J.R. Timmer . 3 | // 4 | // Use of this source code is governed by an MIT-style 5 | // license that can be found in the LICENSE file. 6 | 7 | // +build sqlite_secure_delete_fast 8 | 9 | package sqlite3 10 | 11 | /* 12 | #cgo CFLAGS: -DSQLITE_SECURE_DELETE=FAST 13 | #cgo LDFLAGS: -lm 14 | */ 15 | import "C" 16 | -------------------------------------------------------------------------------- /sqlite3_opt_stat4.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 Yasuhiro Matsumoto . 2 | // Copyright (C) 2018 G.J.R. Timmer . 3 | // 4 | // Use of this source code is governed by an MIT-style 5 | // license that can be found in the LICENSE file. 6 | 7 | // +build sqlite_stat4 8 | 9 | package sqlite3 10 | 11 | /* 12 | #cgo CFLAGS: -DSQLITE_ENABLE_STAT4 13 | #cgo LDFLAGS: -lm 14 | */ 15 | import "C" 16 | -------------------------------------------------------------------------------- /sqlite3_opt_unlock_notify.c: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY 7 | #include 8 | #include "sqlite3-binding.h" 9 | 10 | extern int unlock_notify_wait(sqlite3 *db); 11 | 12 | int 13 | _sqlite3_step_blocking(sqlite3_stmt *stmt) 14 | { 15 | int rv; 16 | sqlite3* db; 17 | 18 | db = sqlite3_db_handle(stmt); 19 | for (;;) { 20 | rv = sqlite3_step(stmt); 21 | if (rv != SQLITE_LOCKED) { 22 | break; 23 | } 24 | if (sqlite3_extended_errcode(db) != SQLITE_LOCKED_SHAREDCACHE) { 25 | break; 26 | } 27 | rv = unlock_notify_wait(db); 28 | if (rv != SQLITE_OK) { 29 | break; 30 | } 31 | sqlite3_reset(stmt); 32 | } 33 | 34 | return rv; 35 | } 36 | 37 | int 38 | _sqlite3_step_row_blocking(sqlite3_stmt* stmt, long long* rowid, long long* changes) 39 | { 40 | int rv; 41 | sqlite3* db; 42 | 43 | db = sqlite3_db_handle(stmt); 44 | for (;;) { 45 | rv = sqlite3_step(stmt); 46 | if (rv!=SQLITE_LOCKED) { 47 | break; 48 | } 49 | if (sqlite3_extended_errcode(db) != SQLITE_LOCKED_SHAREDCACHE) { 50 | break; 51 | } 52 | rv = unlock_notify_wait(db); 53 | if (rv != SQLITE_OK) { 54 | break; 55 | } 56 | sqlite3_reset(stmt); 57 | } 58 | 59 | *rowid = (long long) sqlite3_last_insert_rowid(db); 60 | *changes = (long long) sqlite3_changes(db); 61 | return rv; 62 | } 63 | 64 | int 65 | _sqlite3_prepare_v2_blocking(sqlite3 *db, const char *zSql, int nBytes, sqlite3_stmt **ppStmt, const char **pzTail) 66 | { 67 | int rv; 68 | 69 | for (;;) { 70 | rv = sqlite3_prepare_v2(db, zSql, nBytes, ppStmt, pzTail); 71 | if (rv!=SQLITE_LOCKED) { 72 | break; 73 | } 74 | if (sqlite3_extended_errcode(db) != SQLITE_LOCKED_SHAREDCACHE) { 75 | break; 76 | } 77 | rv = unlock_notify_wait(db); 78 | if (rv != SQLITE_OK) { 79 | break; 80 | } 81 | } 82 | 83 | return rv; 84 | } 85 | #endif 86 | -------------------------------------------------------------------------------- /sqlite3_opt_unlock_notify.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // +build cgo 7 | // +build sqlite_unlock_notify 8 | 9 | package sqlite3 10 | 11 | /* 12 | #cgo CFLAGS: -DSQLITE_ENABLE_UNLOCK_NOTIFY 13 | 14 | #include 15 | #include "sqlite3-binding.h" 16 | 17 | extern void unlock_notify_callback(void *arg, int argc); 18 | */ 19 | import "C" 20 | import ( 21 | "fmt" 22 | "math" 23 | "sync" 24 | "unsafe" 25 | ) 26 | 27 | type unlock_notify_table struct { 28 | sync.Mutex 29 | seqnum uint 30 | table map[uint]chan struct{} 31 | } 32 | 33 | var unt unlock_notify_table = unlock_notify_table{table: make(map[uint]chan struct{})} 34 | 35 | func (t *unlock_notify_table) add(c chan struct{}) uint { 36 | t.Lock() 37 | defer t.Unlock() 38 | h := t.seqnum 39 | t.table[h] = c 40 | t.seqnum++ 41 | return h 42 | } 43 | 44 | func (t *unlock_notify_table) remove(h uint) { 45 | t.Lock() 46 | defer t.Unlock() 47 | delete(t.table, h) 48 | } 49 | 50 | func (t *unlock_notify_table) get(h uint) chan struct{} { 51 | t.Lock() 52 | defer t.Unlock() 53 | c, ok := t.table[h] 54 | if !ok { 55 | panic(fmt.Sprintf("Non-existent key for unlcok-notify channel: %d", h)) 56 | } 57 | return c 58 | } 59 | 60 | //export unlock_notify_callback 61 | func unlock_notify_callback(argv unsafe.Pointer, argc C.int) { 62 | for i := 0; i < int(argc); i++ { 63 | parg := ((*(*[(math.MaxInt32 - 1) / unsafe.Sizeof((*C.uint)(nil))]*[1]uint)(argv))[i]) 64 | arg := *parg 65 | h := arg[0] 66 | c := unt.get(h) 67 | c <- struct{}{} 68 | } 69 | } 70 | 71 | //export unlock_notify_wait 72 | func unlock_notify_wait(db *C.sqlite3) C.int { 73 | // It has to be a bufferred channel to not block in sqlite_unlock_notify 74 | // as sqlite_unlock_notify could invoke the callback before it returns. 75 | c := make(chan struct{}, 1) 76 | defer close(c) 77 | 78 | h := unt.add(c) 79 | defer unt.remove(h) 80 | 81 | pargv := C.malloc(C.sizeof_uint) 82 | defer C.free(pargv) 83 | 84 | argv := (*[1]uint)(pargv) 85 | argv[0] = h 86 | if rv := C.sqlite3_unlock_notify(db, (*[0]byte)(C.unlock_notify_callback), unsafe.Pointer(pargv)); rv != C.SQLITE_OK { 87 | return rv 88 | } 89 | 90 | <-c 91 | 92 | return C.SQLITE_OK 93 | } 94 | -------------------------------------------------------------------------------- /sqlite3_opt_unlock_notify_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // +build sqlite_unlock_notify 7 | 8 | package sqlite3 9 | 10 | import ( 11 | "database/sql" 12 | "fmt" 13 | "os" 14 | "sync" 15 | "testing" 16 | "time" 17 | ) 18 | 19 | func TestUnlockNotify(t *testing.T) { 20 | tempFilename := TempFilename(t) 21 | defer os.Remove(tempFilename) 22 | dsn := fmt.Sprintf("file:%s?cache=shared&mode=rwc&_busy_timeout=%d", tempFilename, 500) 23 | db, err := sql.Open("sqlite3", dsn) 24 | if err != nil { 25 | t.Fatal("Failed to open database:", err) 26 | } 27 | defer db.Close() 28 | 29 | _, err = db.Exec("CREATE TABLE foo(id INTEGER, status INTEGER)") 30 | if err != nil { 31 | t.Fatal("Failed to create table:", err) 32 | } 33 | 34 | tx, err := db.Begin() 35 | if err != nil { 36 | t.Fatal("Failed to begin transaction:", err) 37 | } 38 | 39 | _, err = tx.Exec("INSERT INTO foo(id, status) VALUES(1, 100)") 40 | if err != nil { 41 | t.Fatal("Failed to insert null:", err) 42 | } 43 | 44 | _, err = tx.Exec("UPDATE foo SET status = 200 WHERE id = 1") 45 | if err != nil { 46 | t.Fatal("Failed to update table:", err) 47 | } 48 | 49 | wg := sync.WaitGroup{} 50 | wg.Add(1) 51 | timer := time.NewTimer(500 * time.Millisecond) 52 | go func() { 53 | <-timer.C 54 | err := tx.Commit() 55 | if err != nil { 56 | t.Fatal("Failed to commit transaction:", err) 57 | } 58 | wg.Done() 59 | }() 60 | 61 | rows, err := db.Query("SELECT count(*) from foo") 62 | if err != nil { 63 | t.Fatal("Unable to query foo table:", err) 64 | } 65 | 66 | if rows.Next() { 67 | var count int 68 | if err := rows.Scan(&count); err != nil { 69 | t.Fatal("Failed to Scan rows", err) 70 | } 71 | } 72 | if err := rows.Err(); err != nil { 73 | t.Fatal("Failed at the call to Next:", err) 74 | } 75 | wg.Wait() 76 | 77 | } 78 | 79 | func TestUnlockNotifyMany(t *testing.T) { 80 | tempFilename := TempFilename(t) 81 | defer os.Remove(tempFilename) 82 | dsn := fmt.Sprintf("file:%s?cache=shared&mode=rwc&_busy_timeout=%d", tempFilename, 500) 83 | db, err := sql.Open("sqlite3", dsn) 84 | if err != nil { 85 | t.Fatal("Failed to open database:", err) 86 | } 87 | defer db.Close() 88 | 89 | _, err = db.Exec("CREATE TABLE foo(id INTEGER, status INTEGER)") 90 | if err != nil { 91 | t.Fatal("Failed to create table:", err) 92 | } 93 | 94 | tx, err := db.Begin() 95 | if err != nil { 96 | t.Fatal("Failed to begin transaction:", err) 97 | } 98 | 99 | _, err = tx.Exec("INSERT INTO foo(id, status) VALUES(1, 100)") 100 | if err != nil { 101 | t.Fatal("Failed to insert null:", err) 102 | } 103 | 104 | _, err = tx.Exec("UPDATE foo SET status = 200 WHERE id = 1") 105 | if err != nil { 106 | t.Fatal("Failed to update table:", err) 107 | } 108 | 109 | wg := sync.WaitGroup{} 110 | wg.Add(1) 111 | timer := time.NewTimer(500 * time.Millisecond) 112 | go func() { 113 | <-timer.C 114 | err := tx.Commit() 115 | if err != nil { 116 | t.Fatal("Failed to commit transaction:", err) 117 | } 118 | wg.Done() 119 | }() 120 | 121 | const concurrentQueries = 1000 122 | wg.Add(concurrentQueries) 123 | for i := 0; i < concurrentQueries; i++ { 124 | go func() { 125 | rows, err := db.Query("SELECT count(*) from foo") 126 | if err != nil { 127 | t.Fatal("Unable to query foo table:", err) 128 | } 129 | 130 | if rows.Next() { 131 | var count int 132 | if err := rows.Scan(&count); err != nil { 133 | t.Fatal("Failed to Scan rows", err) 134 | } 135 | } 136 | if err := rows.Err(); err != nil { 137 | t.Fatal("Failed at the call to Next:", err) 138 | } 139 | wg.Done() 140 | }() 141 | } 142 | wg.Wait() 143 | } 144 | 145 | func TestUnlockNotifyDeadlock(t *testing.T) { 146 | tempFilename := TempFilename(t) 147 | defer os.Remove(tempFilename) 148 | dsn := fmt.Sprintf("file:%s?cache=shared&mode=rwc&_busy_timeout=%d", tempFilename, 500) 149 | db, err := sql.Open("sqlite3", dsn) 150 | if err != nil { 151 | t.Fatal("Failed to open database:", err) 152 | } 153 | defer db.Close() 154 | 155 | _, err = db.Exec("CREATE TABLE foo(id INTEGER, status INTEGER)") 156 | if err != nil { 157 | t.Fatal("Failed to create table:", err) 158 | } 159 | 160 | tx, err := db.Begin() 161 | if err != nil { 162 | t.Fatal("Failed to begin transaction:", err) 163 | } 164 | 165 | _, err = tx.Exec("INSERT INTO foo(id, status) VALUES(1, 100)") 166 | if err != nil { 167 | t.Fatal("Failed to insert null:", err) 168 | } 169 | 170 | _, err = tx.Exec("UPDATE foo SET status = 200 WHERE id = 1") 171 | if err != nil { 172 | t.Fatal("Failed to update table:", err) 173 | } 174 | 175 | wg := sync.WaitGroup{} 176 | wg.Add(1) 177 | timer := time.NewTimer(500 * time.Millisecond) 178 | go func() { 179 | <-timer.C 180 | err := tx.Commit() 181 | if err != nil { 182 | t.Fatal("Failed to commit transaction:", err) 183 | } 184 | wg.Done() 185 | }() 186 | 187 | wg.Add(1) 188 | go func() { 189 | tx2, err := db.Begin() 190 | if err != nil { 191 | t.Fatal("Failed to begin transaction:", err) 192 | } 193 | defer tx2.Rollback() 194 | 195 | _, err = tx2.Exec("DELETE FROM foo") 196 | if err != nil { 197 | t.Fatal("Failed to delete table:", err) 198 | } 199 | err = tx2.Commit() 200 | if err != nil { 201 | t.Fatal("Failed to commit transaction:", err) 202 | } 203 | wg.Done() 204 | }() 205 | 206 | rows, err := tx.Query("SELECT count(*) from foo") 207 | if err != nil { 208 | t.Fatal("Unable to query foo table:", err) 209 | } 210 | 211 | if rows.Next() { 212 | var count int 213 | if err := rows.Scan(&count); err != nil { 214 | t.Fatal("Failed to Scan rows", err) 215 | } 216 | } 217 | if err := rows.Err(); err != nil { 218 | t.Fatal("Failed at the call to Next:", err) 219 | } 220 | 221 | wg.Wait() 222 | } 223 | -------------------------------------------------------------------------------- /sqlite3_opt_userauth.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 G.J.R. Timmer . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // +build sqlite_userauth 7 | 8 | package sqlite3 9 | 10 | /* 11 | #cgo CFLAGS: -DSQLITE_USER_AUTHENTICATION 12 | #cgo LDFLAGS: -lm 13 | #ifndef USE_LIBSQLITE3 14 | #include "sqlite3-binding.h" 15 | #else 16 | #include 17 | #endif 18 | #include 19 | 20 | static int 21 | _sqlite3_user_authenticate(sqlite3* db, const char* zUsername, const char* aPW, int nPW) 22 | { 23 | return sqlite3_user_authenticate(db, zUsername, aPW, nPW); 24 | } 25 | 26 | static int 27 | _sqlite3_user_add(sqlite3* db, const char* zUsername, const char* aPW, int nPW, int isAdmin) 28 | { 29 | return sqlite3_user_add(db, zUsername, aPW, nPW, isAdmin); 30 | } 31 | 32 | static int 33 | _sqlite3_user_change(sqlite3* db, const char* zUsername, const char* aPW, int nPW, int isAdmin) 34 | { 35 | return sqlite3_user_change(db, zUsername, aPW, nPW, isAdmin); 36 | } 37 | 38 | static int 39 | _sqlite3_user_delete(sqlite3* db, const char* zUsername) 40 | { 41 | return sqlite3_user_delete(db, zUsername); 42 | } 43 | 44 | static int 45 | _sqlite3_auth_enabled(sqlite3* db) 46 | { 47 | int exists = -1; 48 | 49 | sqlite3_stmt *stmt; 50 | sqlite3_prepare_v2(db, "select count(type) from sqlite_master WHERE type='table' and name='sqlite_user';", -1, &stmt, NULL); 51 | 52 | while ( sqlite3_step(stmt) == SQLITE_ROW) { 53 | exists = sqlite3_column_int(stmt, 0); 54 | } 55 | 56 | sqlite3_finalize(stmt); 57 | 58 | return exists; 59 | } 60 | */ 61 | import "C" 62 | import ( 63 | "errors" 64 | "unsafe" 65 | ) 66 | 67 | const ( 68 | SQLITE_AUTH = C.SQLITE_AUTH 69 | ) 70 | 71 | var ( 72 | ErrUnauthorized = errors.New("SQLITE_AUTH: Unauthorized") 73 | ErrAdminRequired = errors.New("SQLITE_AUTH: Unauthorized; Admin Privileges Required") 74 | ) 75 | 76 | // Authenticate will perform an authentication of the provided username 77 | // and password against the database. 78 | // 79 | // If a database contains the SQLITE_USER table, then the 80 | // call to Authenticate must be invoked with an 81 | // appropriate username and password prior to enable read and write 82 | //access to the database. 83 | // 84 | // Return SQLITE_OK on success or SQLITE_ERROR if the username/password 85 | // combination is incorrect or unknown. 86 | // 87 | // If the SQLITE_USER table is not present in the database file, then 88 | // this interface is a harmless no-op returnning SQLITE_OK. 89 | func (c *SQLiteConn) Authenticate(username, password string) error { 90 | rv := c.authenticate(username, password) 91 | switch rv { 92 | case C.SQLITE_ERROR, C.SQLITE_AUTH: 93 | return ErrUnauthorized 94 | case C.SQLITE_OK: 95 | return nil 96 | default: 97 | return c.lastError() 98 | } 99 | } 100 | 101 | // authenticate provides the actual authentication to SQLite. 102 | // This is not exported for usage in Go. 103 | // It is however exported for usage within SQL by the user. 104 | // 105 | // Returns: 106 | // C.SQLITE_OK (0) 107 | // C.SQLITE_ERROR (1) 108 | // C.SQLITE_AUTH (23) 109 | func (c *SQLiteConn) authenticate(username, password string) int { 110 | // Allocate C Variables 111 | cuser := C.CString(username) 112 | cpass := C.CString(password) 113 | 114 | // Free C Variables 115 | defer func() { 116 | C.free(unsafe.Pointer(cuser)) 117 | C.free(unsafe.Pointer(cpass)) 118 | }() 119 | 120 | return int(C._sqlite3_user_authenticate(c.db, cuser, cpass, C.int(len(password)))) 121 | } 122 | 123 | // AuthUserAdd can be used (by an admin user only) 124 | // to create a new user. When called on a no-authentication-required 125 | // database, this routine converts the database into an authentication- 126 | // required database, automatically makes the added user an 127 | // administrator, and logs in the current connection as that user. 128 | // The AuthUserAdd only works for the "main" database, not 129 | // for any ATTACH-ed databases. Any call to AuthUserAdd by a 130 | // non-admin user results in an error. 131 | func (c *SQLiteConn) AuthUserAdd(username, password string, admin bool) error { 132 | isAdmin := 0 133 | if admin { 134 | isAdmin = 1 135 | } 136 | 137 | rv := c.authUserAdd(username, password, isAdmin) 138 | switch rv { 139 | case C.SQLITE_ERROR, C.SQLITE_AUTH: 140 | return ErrAdminRequired 141 | case C.SQLITE_OK: 142 | return nil 143 | default: 144 | return c.lastError() 145 | } 146 | } 147 | 148 | // authUserAdd enables the User Authentication if not enabled. 149 | // Otherwise it will add a user. 150 | // 151 | // When user authentication is already enabled then this function 152 | // can only be called by an admin. 153 | // 154 | // This is not exported for usage in Go. 155 | // It is however exported for usage within SQL by the user. 156 | // 157 | // Returns: 158 | // C.SQLITE_OK (0) 159 | // C.SQLITE_ERROR (1) 160 | // C.SQLITE_AUTH (23) 161 | func (c *SQLiteConn) authUserAdd(username, password string, admin int) int { 162 | // Allocate C Variables 163 | cuser := C.CString(username) 164 | cpass := C.CString(password) 165 | 166 | // Free C Variables 167 | defer func() { 168 | C.free(unsafe.Pointer(cuser)) 169 | C.free(unsafe.Pointer(cpass)) 170 | }() 171 | 172 | return int(C._sqlite3_user_add(c.db, cuser, cpass, C.int(len(password)), C.int(admin))) 173 | } 174 | 175 | // AuthUserChange can be used to change a users 176 | // login credentials or admin privilege. Any user can change their own 177 | // login credentials. Only an admin user can change another users login 178 | // credentials or admin privilege setting. No user may change their own 179 | // admin privilege setting. 180 | func (c *SQLiteConn) AuthUserChange(username, password string, admin bool) error { 181 | isAdmin := 0 182 | if admin { 183 | isAdmin = 1 184 | } 185 | 186 | rv := c.authUserChange(username, password, isAdmin) 187 | switch rv { 188 | case C.SQLITE_ERROR, C.SQLITE_AUTH: 189 | return ErrAdminRequired 190 | case C.SQLITE_OK: 191 | return nil 192 | default: 193 | return c.lastError() 194 | } 195 | } 196 | 197 | // authUserChange allows to modify a user. 198 | // Users can change their own password. 199 | // 200 | // Only admins can change passwords for other users 201 | // and modify the admin flag. 202 | // 203 | // The admin flag of the current logged in user cannot be changed. 204 | // THis ensures that their is always an admin. 205 | // 206 | // This is not exported for usage in Go. 207 | // It is however exported for usage within SQL by the user. 208 | // 209 | // Returns: 210 | // C.SQLITE_OK (0) 211 | // C.SQLITE_ERROR (1) 212 | // C.SQLITE_AUTH (23) 213 | func (c *SQLiteConn) authUserChange(username, password string, admin int) int { 214 | // Allocate C Variables 215 | cuser := C.CString(username) 216 | cpass := C.CString(password) 217 | 218 | // Free C Variables 219 | defer func() { 220 | C.free(unsafe.Pointer(cuser)) 221 | C.free(unsafe.Pointer(cpass)) 222 | }() 223 | 224 | return int(C._sqlite3_user_change(c.db, cuser, cpass, C.int(len(password)), C.int(admin))) 225 | } 226 | 227 | // AuthUserDelete can be used (by an admin user only) 228 | // to delete a user. The currently logged-in user cannot be deleted, 229 | // which guarantees that there is always an admin user and hence that 230 | // the database cannot be converted into a no-authentication-required 231 | // database. 232 | func (c *SQLiteConn) AuthUserDelete(username string) error { 233 | rv := c.authUserDelete(username) 234 | switch rv { 235 | case C.SQLITE_ERROR, C.SQLITE_AUTH: 236 | return ErrAdminRequired 237 | case C.SQLITE_OK: 238 | return nil 239 | default: 240 | return c.lastError() 241 | } 242 | } 243 | 244 | // authUserDelete can be used to delete a user. 245 | // 246 | // This function can only be executed by an admin. 247 | // 248 | // This is not exported for usage in Go. 249 | // It is however exported for usage within SQL by the user. 250 | // 251 | // Returns: 252 | // C.SQLITE_OK (0) 253 | // C.SQLITE_ERROR (1) 254 | // C.SQLITE_AUTH (23) 255 | func (c *SQLiteConn) authUserDelete(username string) int { 256 | // Allocate C Variables 257 | cuser := C.CString(username) 258 | 259 | // Free C Variables 260 | defer func() { 261 | C.free(unsafe.Pointer(cuser)) 262 | }() 263 | 264 | return int(C._sqlite3_user_delete(c.db, cuser)) 265 | } 266 | 267 | // AuthEnabled checks if the database is protected by user authentication 268 | func (c *SQLiteConn) AuthEnabled() (exists bool) { 269 | rv := c.authEnabled() 270 | if rv == 1 { 271 | exists = true 272 | } 273 | 274 | return 275 | } 276 | 277 | // authEnabled perform the actual check for user authentication. 278 | // 279 | // This is not exported for usage in Go. 280 | // It is however exported for usage within SQL by the user. 281 | // 282 | // Returns: 283 | // 0 - Disabled 284 | // 1 - Enabled 285 | func (c *SQLiteConn) authEnabled() int { 286 | return int(C._sqlite3_auth_enabled(c.db)) 287 | } 288 | 289 | // EOF 290 | -------------------------------------------------------------------------------- /sqlite3_opt_userauth_omit.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 G.J.R. Timmer . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // +build !sqlite_userauth 7 | 8 | package sqlite3 9 | 10 | import ( 11 | "C" 12 | ) 13 | 14 | // Authenticate will perform an authentication of the provided username 15 | // and password against the database. 16 | // 17 | // If a database contains the SQLITE_USER table, then the 18 | // call to Authenticate must be invoked with an 19 | // appropriate username and password prior to enable read and write 20 | //access to the database. 21 | // 22 | // Return SQLITE_OK on success or SQLITE_ERROR if the username/password 23 | // combination is incorrect or unknown. 24 | // 25 | // If the SQLITE_USER table is not present in the database file, then 26 | // this interface is a harmless no-op returnning SQLITE_OK. 27 | func (c *SQLiteConn) Authenticate(username, password string) error { 28 | // NOOP 29 | return nil 30 | } 31 | 32 | // authenticate provides the actual authentication to SQLite. 33 | // This is not exported for usage in Go. 34 | // It is however exported for usage within SQL by the user. 35 | // 36 | // Returns: 37 | // C.SQLITE_OK (0) 38 | // C.SQLITE_ERROR (1) 39 | // C.SQLITE_AUTH (23) 40 | func (c *SQLiteConn) authenticate(username, password string) int { 41 | // NOOP 42 | return 0 43 | } 44 | 45 | // AuthUserAdd can be used (by an admin user only) 46 | // to create a new user. When called on a no-authentication-required 47 | // database, this routine converts the database into an authentication- 48 | // required database, automatically makes the added user an 49 | // administrator, and logs in the current connection as that user. 50 | // The AuthUserAdd only works for the "main" database, not 51 | // for any ATTACH-ed databases. Any call to AuthUserAdd by a 52 | // non-admin user results in an error. 53 | func (c *SQLiteConn) AuthUserAdd(username, password string, admin bool) error { 54 | // NOOP 55 | return nil 56 | } 57 | 58 | // authUserAdd enables the User Authentication if not enabled. 59 | // Otherwise it will add a user. 60 | // 61 | // When user authentication is already enabled then this function 62 | // can only be called by an admin. 63 | // 64 | // This is not exported for usage in Go. 65 | // It is however exported for usage within SQL by the user. 66 | // 67 | // Returns: 68 | // C.SQLITE_OK (0) 69 | // C.SQLITE_ERROR (1) 70 | // C.SQLITE_AUTH (23) 71 | func (c *SQLiteConn) authUserAdd(username, password string, admin int) int { 72 | // NOOP 73 | return 0 74 | } 75 | 76 | // AuthUserChange can be used to change a users 77 | // login credentials or admin privilege. Any user can change their own 78 | // login credentials. Only an admin user can change another users login 79 | // credentials or admin privilege setting. No user may change their own 80 | // admin privilege setting. 81 | func (c *SQLiteConn) AuthUserChange(username, password string, admin bool) error { 82 | // NOOP 83 | return nil 84 | } 85 | 86 | // authUserChange allows to modify a user. 87 | // Users can change their own password. 88 | // 89 | // Only admins can change passwords for other users 90 | // and modify the admin flag. 91 | // 92 | // The admin flag of the current logged in user cannot be changed. 93 | // THis ensures that their is always an admin. 94 | // 95 | // This is not exported for usage in Go. 96 | // It is however exported for usage within SQL by the user. 97 | // 98 | // Returns: 99 | // C.SQLITE_OK (0) 100 | // C.SQLITE_ERROR (1) 101 | // C.SQLITE_AUTH (23) 102 | func (c *SQLiteConn) authUserChange(username, password string, admin int) int { 103 | // NOOP 104 | return 0 105 | } 106 | 107 | // AuthUserDelete can be used (by an admin user only) 108 | // to delete a user. The currently logged-in user cannot be deleted, 109 | // which guarantees that there is always an admin user and hence that 110 | // the database cannot be converted into a no-authentication-required 111 | // database. 112 | func (c *SQLiteConn) AuthUserDelete(username string) error { 113 | // NOOP 114 | return nil 115 | } 116 | 117 | // authUserDelete can be used to delete a user. 118 | // 119 | // This function can only be executed by an admin. 120 | // 121 | // This is not exported for usage in Go. 122 | // It is however exported for usage within SQL by the user. 123 | // 124 | // Returns: 125 | // C.SQLITE_OK (0) 126 | // C.SQLITE_ERROR (1) 127 | // C.SQLITE_AUTH (23) 128 | func (c *SQLiteConn) authUserDelete(username string) int { 129 | // NOOP 130 | return 0 131 | } 132 | 133 | // AuthEnabled checks if the database is protected by user authentication 134 | func (c *SQLiteConn) AuthEnabled() (exists bool) { 135 | // NOOP 136 | return false 137 | } 138 | 139 | // authEnabled perform the actual check for user authentication. 140 | // 141 | // This is not exported for usage in Go. 142 | // It is however exported for usage within SQL by the user. 143 | // 144 | // Returns: 145 | // 0 - Disabled 146 | // 1 - Enabled 147 | func (c *SQLiteConn) authEnabled() int { 148 | // NOOP 149 | return 0 150 | } 151 | 152 | // EOF 153 | -------------------------------------------------------------------------------- /sqlite3_opt_vacuum_full.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 Yasuhiro Matsumoto . 2 | // Copyright (C) 2018 G.J.R. Timmer . 3 | // 4 | // Use of this source code is governed by an MIT-style 5 | // license that can be found in the LICENSE file. 6 | 7 | // +build sqlite_vacuum_full 8 | 9 | package sqlite3 10 | 11 | /* 12 | #cgo CFLAGS: -DSQLITE_DEFAULT_AUTOVACUUM=1 13 | #cgo LDFLAGS: -lm 14 | */ 15 | import "C" 16 | -------------------------------------------------------------------------------- /sqlite3_opt_vacuum_incr.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 Yasuhiro Matsumoto . 2 | // Copyright (C) 2018 G.J.R. Timmer . 3 | // 4 | // Use of this source code is governed by an MIT-style 5 | // license that can be found in the LICENSE file. 6 | 7 | // +build sqlite_vacuum_incr 8 | 9 | package sqlite3 10 | 11 | /* 12 | #cgo CFLAGS: -DSQLITE_DEFAULT_AUTOVACUUM=2 13 | #cgo LDFLAGS: -lm 14 | */ 15 | import "C" 16 | -------------------------------------------------------------------------------- /sqlite3_other.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // +build !windows 7 | 8 | package sqlite3 9 | 10 | /* 11 | #cgo CFLAGS: -I. 12 | #cgo linux LDFLAGS: -ldl 13 | #cgo linux,ppc LDFLAGS: -lpthread 14 | #cgo linux,ppc64 LDFLAGS: -lpthread 15 | #cgo linux,ppc64le LDFLAGS: -lpthread 16 | */ 17 | import "C" 18 | -------------------------------------------------------------------------------- /sqlite3_solaris.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // +build solaris 7 | 8 | package sqlite3 9 | 10 | /* 11 | #cgo CFLAGS: -D__EXTENSIONS__=1 12 | #cgo LDFLAGS: -lc 13 | */ 14 | import "C" 15 | -------------------------------------------------------------------------------- /sqlite3_trace.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // +build sqlite_trace trace 7 | 8 | package sqlite3 9 | 10 | /* 11 | #ifndef USE_LIBSQLITE3 12 | #include "sqlite3-binding.h" 13 | #else 14 | #include 15 | #endif 16 | #include 17 | 18 | int traceCallbackTrampoline(unsigned int traceEventCode, void *ctx, void *p, void *x); 19 | */ 20 | import "C" 21 | 22 | import ( 23 | "fmt" 24 | "strings" 25 | "sync" 26 | "unsafe" 27 | ) 28 | 29 | // Trace... constants identify the possible events causing callback invocation. 30 | // Values are same as the corresponding SQLite Trace Event Codes. 31 | const ( 32 | TraceStmt = uint32(C.SQLITE_TRACE_STMT) 33 | TraceProfile = uint32(C.SQLITE_TRACE_PROFILE) 34 | TraceRow = uint32(C.SQLITE_TRACE_ROW) 35 | TraceClose = uint32(C.SQLITE_TRACE_CLOSE) 36 | ) 37 | 38 | type TraceInfo struct { 39 | // Pack together the shorter fields, to keep the struct smaller. 40 | // On a 64-bit machine there would be padding 41 | // between EventCode and ConnHandle; having AutoCommit here is "free": 42 | EventCode uint32 43 | AutoCommit bool 44 | ConnHandle uintptr 45 | 46 | // Usually filled, unless EventCode = TraceClose = SQLITE_TRACE_CLOSE: 47 | // identifier for a prepared statement: 48 | StmtHandle uintptr 49 | 50 | // Two strings filled when EventCode = TraceStmt = SQLITE_TRACE_STMT: 51 | // (1) either the unexpanded SQL text of the prepared statement, or 52 | // an SQL comment that indicates the invocation of a trigger; 53 | // (2) expanded SQL, if requested and if (1) is not an SQL comment. 54 | StmtOrTrigger string 55 | ExpandedSQL string // only if requested (TraceConfig.WantExpandedSQL = true) 56 | 57 | // filled when EventCode = TraceProfile = SQLITE_TRACE_PROFILE: 58 | // estimated number of nanoseconds that the prepared statement took to run: 59 | RunTimeNanosec int64 60 | 61 | DBError Error 62 | } 63 | 64 | // TraceUserCallback gives the signature for a trace function 65 | // provided by the user (Go application programmer). 66 | // SQLite 3.14 documentation (as of September 2, 2016) 67 | // for SQL Trace Hook = sqlite3_trace_v2(): 68 | // The integer return value from the callback is currently ignored, 69 | // though this may change in future releases. Callback implementations 70 | // should return zero to ensure future compatibility. 71 | type TraceUserCallback func(TraceInfo) int 72 | 73 | type TraceConfig struct { 74 | Callback TraceUserCallback 75 | EventMask uint32 76 | WantExpandedSQL bool 77 | } 78 | 79 | func fillDBError(dbErr *Error, db *C.sqlite3) { 80 | // See SQLiteConn.lastError(), in file 'sqlite3.go' at the time of writing (Sept 5, 2016) 81 | dbErr.Code = ErrNo(C.sqlite3_errcode(db)) 82 | dbErr.ExtendedCode = ErrNoExtended(C.sqlite3_extended_errcode(db)) 83 | dbErr.err = C.GoString(C.sqlite3_errmsg(db)) 84 | } 85 | 86 | func fillExpandedSQL(info *TraceInfo, db *C.sqlite3, pStmt unsafe.Pointer) { 87 | if pStmt == nil { 88 | panic("No SQLite statement pointer in P arg of trace_v2 callback") 89 | } 90 | 91 | expSQLiteCStr := C.sqlite3_expanded_sql((*C.sqlite3_stmt)(pStmt)) 92 | defer C.sqlite3_free(unsafe.Pointer(expSQLiteCStr)) 93 | if expSQLiteCStr == nil { 94 | fillDBError(&info.DBError, db) 95 | return 96 | } 97 | info.ExpandedSQL = C.GoString(expSQLiteCStr) 98 | } 99 | 100 | //export traceCallbackTrampoline 101 | func traceCallbackTrampoline( 102 | traceEventCode C.uint, 103 | // Parameter named 'C' in SQLite docs = Context given at registration: 104 | ctx unsafe.Pointer, 105 | // Parameter named 'P' in SQLite docs (Primary event data?): 106 | p unsafe.Pointer, 107 | // Parameter named 'X' in SQLite docs (eXtra event data?): 108 | xValue unsafe.Pointer) C.int { 109 | 110 | eventCode := uint32(traceEventCode) 111 | 112 | if ctx == nil { 113 | panic(fmt.Sprintf("No context (ev 0x%x)", traceEventCode)) 114 | } 115 | 116 | contextDB := (*C.sqlite3)(ctx) 117 | connHandle := uintptr(ctx) 118 | 119 | var traceConf TraceConfig 120 | var found bool 121 | if eventCode == TraceClose { 122 | // clean up traceMap: 'pop' means get and delete 123 | traceConf, found = popTraceMapping(connHandle) 124 | } else { 125 | traceConf, found = lookupTraceMapping(connHandle) 126 | } 127 | 128 | if !found { 129 | panic(fmt.Sprintf("Mapping not found for handle 0x%x (ev 0x%x)", 130 | connHandle, eventCode)) 131 | } 132 | 133 | var info TraceInfo 134 | 135 | info.EventCode = eventCode 136 | info.AutoCommit = (int(C.sqlite3_get_autocommit(contextDB)) != 0) 137 | info.ConnHandle = connHandle 138 | 139 | switch eventCode { 140 | case TraceStmt: 141 | info.StmtHandle = uintptr(p) 142 | 143 | var xStr string 144 | if xValue != nil { 145 | xStr = C.GoString((*C.char)(xValue)) 146 | } 147 | info.StmtOrTrigger = xStr 148 | if !strings.HasPrefix(xStr, "--") { 149 | // Not SQL comment, therefore the current event 150 | // is not related to a trigger. 151 | // The user might want to receive the expanded SQL; 152 | // let's check: 153 | if traceConf.WantExpandedSQL { 154 | fillExpandedSQL(&info, contextDB, p) 155 | } 156 | } 157 | 158 | case TraceProfile: 159 | info.StmtHandle = uintptr(p) 160 | 161 | if xValue == nil { 162 | panic("NULL pointer in X arg of trace_v2 callback for SQLITE_TRACE_PROFILE event") 163 | } 164 | 165 | info.RunTimeNanosec = *(*int64)(xValue) 166 | 167 | // sample the error //TODO: is it safe? is it useful? 168 | fillDBError(&info.DBError, contextDB) 169 | 170 | case TraceRow: 171 | info.StmtHandle = uintptr(p) 172 | 173 | case TraceClose: 174 | handle := uintptr(p) 175 | if handle != info.ConnHandle { 176 | panic(fmt.Sprintf("Different conn handle 0x%x (expected 0x%x) in SQLITE_TRACE_CLOSE event.", 177 | handle, info.ConnHandle)) 178 | } 179 | 180 | default: 181 | // Pass unsupported events to the user callback (if configured); 182 | // let the user callback decide whether to panic or ignore them. 183 | } 184 | 185 | // Do not execute user callback when the event was not requested by user! 186 | // Remember that the Close event is always selected when 187 | // registering this callback trampoline with SQLite --- for cleanup. 188 | // In the future there may be more events forced to "selected" in SQLite 189 | // for the driver's needs. 190 | if traceConf.EventMask&eventCode == 0 { 191 | return 0 192 | } 193 | 194 | r := 0 195 | if traceConf.Callback != nil { 196 | r = traceConf.Callback(info) 197 | } 198 | return C.int(r) 199 | } 200 | 201 | type traceMapEntry struct { 202 | config TraceConfig 203 | } 204 | 205 | var traceMapLock sync.Mutex 206 | var traceMap = make(map[uintptr]traceMapEntry) 207 | 208 | func addTraceMapping(connHandle uintptr, traceConf TraceConfig) { 209 | traceMapLock.Lock() 210 | defer traceMapLock.Unlock() 211 | 212 | oldEntryCopy, found := traceMap[connHandle] 213 | if found { 214 | panic(fmt.Sprintf("Adding trace config %v: handle 0x%x already registered (%v).", 215 | traceConf, connHandle, oldEntryCopy.config)) 216 | } 217 | traceMap[connHandle] = traceMapEntry{config: traceConf} 218 | } 219 | 220 | func lookupTraceMapping(connHandle uintptr) (TraceConfig, bool) { 221 | traceMapLock.Lock() 222 | defer traceMapLock.Unlock() 223 | 224 | entryCopy, found := traceMap[connHandle] 225 | return entryCopy.config, found 226 | } 227 | 228 | // 'pop' = get and delete from map before returning the value to the caller 229 | func popTraceMapping(connHandle uintptr) (TraceConfig, bool) { 230 | traceMapLock.Lock() 231 | defer traceMapLock.Unlock() 232 | 233 | entryCopy, found := traceMap[connHandle] 234 | if found { 235 | delete(traceMap, connHandle) 236 | } 237 | return entryCopy.config, found 238 | } 239 | 240 | // SetTrace installs or removes the trace callback for the given database connection. 241 | // It's not named 'RegisterTrace' because only one callback can be kept and called. 242 | // Calling SetTrace a second time on same database connection 243 | // overrides (cancels) any prior callback and all its settings: 244 | // event mask, etc. 245 | func (c *SQLiteConn) SetTrace(requested *TraceConfig) error { 246 | connHandle := uintptr(unsafe.Pointer(c.db)) 247 | 248 | _, _ = popTraceMapping(connHandle) 249 | 250 | if requested == nil { 251 | // The traceMap entry was deleted already by popTraceMapping(): 252 | // can disable all events now, no need to watch for TraceClose. 253 | err := c.setSQLiteTrace(0) 254 | return err 255 | } 256 | 257 | reqCopy := *requested 258 | 259 | // Disable potentially expensive operations 260 | // if their result will not be used. We are doing this 261 | // just in case the caller provided nonsensical input. 262 | if reqCopy.EventMask&TraceStmt == 0 { 263 | reqCopy.WantExpandedSQL = false 264 | } 265 | 266 | addTraceMapping(connHandle, reqCopy) 267 | 268 | // The callback trampoline function does cleanup on Close event, 269 | // regardless of the presence or absence of the user callback. 270 | // Therefore it needs the Close event to be selected: 271 | actualEventMask := uint(reqCopy.EventMask | TraceClose) 272 | err := c.setSQLiteTrace(actualEventMask) 273 | return err 274 | } 275 | 276 | func (c *SQLiteConn) setSQLiteTrace(sqliteEventMask uint) error { 277 | rv := C.sqlite3_trace_v2(c.db, 278 | C.uint(sqliteEventMask), 279 | (*[0]byte)(unsafe.Pointer(C.traceCallbackTrampoline)), 280 | unsafe.Pointer(c.db)) // Fourth arg is same as first: we are 281 | // passing the database connection handle as callback context. 282 | 283 | if rv != C.SQLITE_OK { 284 | return c.lastError() 285 | } 286 | return nil 287 | } 288 | -------------------------------------------------------------------------------- /sqlite3_type.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 Yasuhiro Matsumoto . 2 | // Use of this source code is governed by an MIT-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package sqlite3 6 | 7 | /* 8 | #ifndef USE_LIBSQLITE3 9 | #include "sqlite3-binding.h" 10 | #else 11 | #include 12 | #endif 13 | */ 14 | import "C" 15 | import ( 16 | "database/sql" 17 | "reflect" 18 | "strings" 19 | ) 20 | 21 | // ColumnTypeDatabaseTypeName implement RowsColumnTypeDatabaseTypeName. 22 | func (rc *SQLiteRows) ColumnTypeDatabaseTypeName(i int) string { 23 | return C.GoString(C.sqlite3_column_decltype(rc.s.s, C.int(i))) 24 | } 25 | 26 | /* 27 | func (rc *SQLiteRows) ColumnTypeLength(index int) (length int64, ok bool) { 28 | return 0, false 29 | } 30 | 31 | func (rc *SQLiteRows) ColumnTypePrecisionScale(index int) (precision, scale int64, ok bool) { 32 | return 0, 0, false 33 | } 34 | */ 35 | 36 | // ColumnTypeNullable implement RowsColumnTypeNullable. 37 | func (rc *SQLiteRows) ColumnTypeNullable(i int) (nullable, ok bool) { 38 | return true, true 39 | } 40 | 41 | // ColumnTypeScanType implement RowsColumnTypeScanType. 42 | func (rc *SQLiteRows) ColumnTypeScanType(i int) reflect.Type { 43 | //ct := C.sqlite3_column_type(rc.s.s, C.int(i)) // Always returns 5 44 | return scanType(C.GoString(C.sqlite3_column_decltype(rc.s.s, C.int(i)))) 45 | } 46 | 47 | const ( 48 | SQLITE_INTEGER = iota 49 | SQLITE_TEXT 50 | SQLITE_BLOB 51 | SQLITE_REAL 52 | SQLITE_NUMERIC 53 | SQLITE_TIME 54 | SQLITE_BOOL 55 | SQLITE_NULL 56 | ) 57 | 58 | func scanType(cdt string) reflect.Type { 59 | t := strings.ToUpper(cdt) 60 | i := databaseTypeConvSqlite(t) 61 | switch i { 62 | case SQLITE_INTEGER: 63 | return reflect.TypeOf(sql.NullInt64{}) 64 | case SQLITE_TEXT: 65 | return reflect.TypeOf(sql.NullString{}) 66 | case SQLITE_BLOB: 67 | return reflect.TypeOf(sql.RawBytes{}) 68 | case SQLITE_REAL: 69 | return reflect.TypeOf(sql.NullFloat64{}) 70 | case SQLITE_NUMERIC: 71 | return reflect.TypeOf(sql.NullFloat64{}) 72 | case SQLITE_BOOL: 73 | return reflect.TypeOf(sql.NullBool{}) 74 | case SQLITE_TIME: 75 | return reflect.TypeOf(sql.NullTime{}) 76 | } 77 | return reflect.TypeOf(new(interface{})) 78 | } 79 | 80 | func databaseTypeConvSqlite(t string) int { 81 | if strings.Contains(t, "INT") { 82 | return SQLITE_INTEGER 83 | } 84 | if t == "CLOB" || t == "TEXT" || 85 | strings.Contains(t, "CHAR") { 86 | return SQLITE_TEXT 87 | } 88 | if t == "BLOB" { 89 | return SQLITE_BLOB 90 | } 91 | if t == "REAL" || t == "FLOAT" || 92 | strings.Contains(t, "DOUBLE") { 93 | return SQLITE_REAL 94 | } 95 | if t == "DATE" || t == "DATETIME" || 96 | t == "TIMESTAMP" { 97 | return SQLITE_TIME 98 | } 99 | if t == "NUMERIC" || 100 | strings.Contains(t, "DECIMAL") { 101 | return SQLITE_NUMERIC 102 | } 103 | if t == "BOOLEAN" { 104 | return SQLITE_BOOL 105 | } 106 | 107 | return SQLITE_NULL 108 | } 109 | -------------------------------------------------------------------------------- /sqlite3_usleep_windows.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 G.J.R. Timmer . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // +build cgo 7 | 8 | package sqlite3 9 | 10 | // usleep is a function available on *nix based systems. 11 | // This function is not present in Windows. 12 | // Windows has a sleep function but this works with seconds 13 | // and not with microseconds as usleep. 14 | // 15 | // This code should improve performance on windows because 16 | // without the presence of usleep SQLite waits 1 second. 17 | // 18 | // Source: https://github.com/php/php-src/blob/PHP-5.0/win32/time.c 19 | // License: https://github.com/php/php-src/blob/PHP-5.0/LICENSE 20 | // Details: https://stackoverflow.com/questions/5801813/c-usleep-is-obsolete-workarounds-for-windows-mingw?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa 21 | 22 | /* 23 | #include 24 | 25 | void usleep(__int64 usec) 26 | { 27 | HANDLE timer; 28 | LARGE_INTEGER ft; 29 | 30 | // Convert to 100 nanosecond interval, negative value indicates relative time 31 | ft.QuadPart = -(10*usec); 32 | 33 | timer = CreateWaitableTimer(NULL, TRUE, NULL); 34 | SetWaitableTimer(timer, &ft, 0, NULL, NULL, 0); 35 | WaitForSingleObject(timer, INFINITE); 36 | CloseHandle(timer); 37 | } 38 | */ 39 | import "C" 40 | 41 | // EOF 42 | -------------------------------------------------------------------------------- /sqlite3_windows.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // +build windows 7 | 8 | package sqlite3 9 | 10 | /* 11 | #cgo CFLAGS: -I. 12 | #cgo CFLAGS: -fno-stack-check 13 | #cgo CFLAGS: -fno-stack-protector 14 | #cgo CFLAGS: -mno-stack-arg-probe 15 | #cgo LDFLAGS: -lmingwex -lmingw32 16 | #cgo windows,386 CFLAGS: -D_USE_32BIT_TIME_T 17 | */ 18 | import "C" 19 | -------------------------------------------------------------------------------- /sqlite3mc.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Name: sqlite3mc.h 3 | ** Purpose: Header file for SQLite3 Multiple Ciphers support 4 | ** Author: Ulrich Telle 5 | ** Created: 2020-03-01 6 | ** Copyright: (c) 2019-2021 Ulrich Telle 7 | ** License: MIT 8 | */ 9 | 10 | #ifndef SQLITE3MC_H_ 11 | #define SQLITE3MC_H_ 12 | 13 | /* 14 | ** Define SQLite3 Multiple Ciphers version information 15 | */ 16 | #include "wxsqlite3/sqlite3mc_version.h" 17 | 18 | /* 19 | ** Define SQLite3 API 20 | */ 21 | #include "wxsqlite3/sqlite3.h" 22 | 23 | #ifdef SQLITE_USER_AUTHENTICATION 24 | #include "wxsqlite3/sqlite3userauth.h" 25 | #endif 26 | 27 | /* 28 | ** Symbols for ciphers 29 | */ 30 | #define CODEC_TYPE_UNKNOWN 0 31 | #define CODEC_TYPE_AES128 1 32 | #define CODEC_TYPE_AES256 2 33 | #define CODEC_TYPE_CHACHA20 3 34 | #define CODEC_TYPE_SQLCIPHER 4 35 | #define CODEC_TYPE_RC4 5 36 | #define CODEC_TYPE_MAX 5 37 | 38 | /* 39 | ** Definition of API functions 40 | */ 41 | 42 | /* 43 | ** Define Windows specific SQLite API functions (not defined in sqlite3.h) 44 | */ 45 | #if SQLITE_OS_WIN == 1 46 | 47 | #ifdef __cplusplus 48 | extern "C" { 49 | #endif 50 | 51 | SQLITE_API int sqlite3_win32_set_directory(unsigned long type, void* zValue); 52 | 53 | #ifdef __cplusplus 54 | } 55 | #endif 56 | 57 | #endif 58 | 59 | #ifdef __cplusplus 60 | extern "C" { 61 | #endif 62 | 63 | /* 64 | ** Specify the key for an encrypted database. 65 | ** This routine should be called right after sqlite3_open(). 66 | ** 67 | ** Arguments: 68 | ** db - Database to be encrypted 69 | ** zDbName - Name of the database (e.g. "main") 70 | ** pKey - Passphrase 71 | ** nKey - Length of passphrase 72 | */ 73 | SQLITE_API int sqlite3_key(sqlite3* db, const void* pKey, int nKey); 74 | SQLITE_API int sqlite3_key_v2(sqlite3* db, const char* zDbName, const void* pKey, int nKey); 75 | 76 | /* 77 | ** Change the key on an open database. 78 | ** If the current database is not encrypted, this routine will encrypt 79 | ** it. If pNew==0 or nNew==0, the database is decrypted. 80 | ** 81 | ** Arguments: 82 | ** db - Database to be encrypted 83 | ** zDbName - Name of the database (e.g. "main") 84 | ** pKey - Passphrase 85 | ** nKey - Length of passphrase 86 | */ 87 | SQLITE_API int sqlite3_rekey(sqlite3* db, const void* pKey, int nKey); 88 | SQLITE_API int sqlite3_rekey_v2(sqlite3* db, const char* zDbName, const void* pKey, int nKey); 89 | 90 | /* 91 | ** Specify the activation key for a SEE database. 92 | ** Unless activated, none of the SEE routines will work. 93 | ** 94 | ** Arguments: 95 | ** zPassPhrase - Activation phrase 96 | ** 97 | ** Note: Provided only for API compatibility with SEE. 98 | ** Encryption support of SQLite3 Multi Cipher is always enabled. 99 | */ 100 | SQLITE_API void sqlite3_activate_see(const char* zPassPhrase); 101 | 102 | /* 103 | ** Define functions for the configuration of the wxSQLite3 encryption extension 104 | */ 105 | SQLITE_API int sqlite3mc_config(sqlite3* db, const char* paramName, int newValue); 106 | SQLITE_API int sqlite3mc_config_cipher(sqlite3* db, const char* cipherName, const char* paramName, int newValue); 107 | SQLITE_API unsigned char* sqlite3mc_codec_data(sqlite3* db, const char* zDbName, const char* paramName); 108 | SQLITE_API const char* sqlite3mc_version(); 109 | 110 | #ifdef SQLITE3MC_WXSQLITE3_COMPATIBLE 111 | SQLITE_API int wxsqlite3_config(sqlite3* db, const char* paramName, int newValue); 112 | SQLITE_API int wxsqlite3_config_cipher(sqlite3* db, const char* cipherName, const char* paramName, int newValue); 113 | SQLITE_API unsigned char* wxsqlite3_codec_data(sqlite3* db, const char* zDbName, const char* paramName); 114 | #endif 115 | 116 | #ifdef __cplusplus 117 | } 118 | #endif 119 | 120 | /* 121 | ** Define public SQLite3 Multiple Ciphers VFS interface 122 | */ 123 | #include "wxsqlite3/sqlite3mc_vfs.h" 124 | 125 | #endif 126 | -------------------------------------------------------------------------------- /static_mock.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // +build !cgo 7 | 8 | package sqlite3 9 | 10 | import ( 11 | "database/sql" 12 | "database/sql/driver" 13 | "errors" 14 | ) 15 | 16 | var errorMsg = errors.New("Binary was compiled with 'CGO_ENABLED=0', go-sqlite3 requires cgo to work. This is a stub") 17 | 18 | func init() { 19 | sql.Register("sqlite3", &SQLiteDriver{}) 20 | } 21 | 22 | type ( 23 | SQLiteDriver struct { 24 | Extensions []string 25 | ConnectHook func(*SQLiteConn) error 26 | } 27 | SQLiteConn struct{} 28 | ) 29 | 30 | func (SQLiteDriver) Open(s string) (driver.Conn, error) { return nil, errorMsg } 31 | func (c *SQLiteConn) RegisterAggregator(string, interface{}, bool) error { return errorMsg } 32 | func (c *SQLiteConn) RegisterAuthorizer(func(int, string, string, string) int) {} 33 | func (c *SQLiteConn) RegisterCollation(string, func(string, string) int) error { return errorMsg } 34 | func (c *SQLiteConn) RegisterCommitHook(func() int) {} 35 | func (c *SQLiteConn) RegisterFunc(string, interface{}, bool) error { return errorMsg } 36 | func (c *SQLiteConn) RegisterRollbackHook(func()) {} 37 | func (c *SQLiteConn) RegisterUpdateHook(func(int, string, string, int64)) {} 38 | -------------------------------------------------------------------------------- /wxsqlite3/carray.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** 2020-11-17 3 | ** 4 | ** The author disclaims copyright to this source code. In place of 5 | ** a legal notice, here is a blessing: 6 | ** 7 | ** May you do good and not evil. 8 | ** May you find forgiveness for yourself and forgive others. 9 | ** May you share freely, never taking more than you give. 10 | ** 11 | ************************************************************************* 12 | ** 13 | ** Interface definitions for the CARRAY table-valued function 14 | ** extension. 15 | */ 16 | 17 | #ifndef _CARRAY_H 18 | #define _CARRAY_H 19 | 20 | #include "sqlite3.h" /* Required for error code definitions */ 21 | 22 | #ifdef __cplusplus 23 | extern "C" { 24 | #endif 25 | 26 | /* Use this interface to bind an array to the single-argument version 27 | ** of CARRAY(). 28 | */ 29 | SQLITE_API int sqlite3_carray_bind( 30 | sqlite3_stmt *pStmt, /* Statement to be bound */ 31 | int i, /* Parameter index */ 32 | void *aData, /* Pointer to array data */ 33 | int nData, /* Number of data elements */ 34 | int mFlags, /* CARRAY flags */ 35 | void (*xDel)(void*) /* Destructgor for aData*/ 36 | ); 37 | 38 | /* Allowed values for the mFlags parameter to sqlite3_carray_bind(). 39 | */ 40 | #define CARRAY_INT32 0 /* Data is 32-bit signed integers */ 41 | #define CARRAY_INT64 1 /* Data is 64-bit signed integers */ 42 | #define CARRAY_DOUBLE 2 /* Data is doubles */ 43 | #define CARRAY_TEXT 3 /* Data is char* */ 44 | 45 | #ifdef __cplusplus 46 | } /* end of the 'extern "C"' block */ 47 | #endif 48 | 49 | #endif /* ifndef _CARRAY_H */ 50 | 51 | -------------------------------------------------------------------------------- /wxsqlite3/cipher_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Name: cipher_config.h 3 | ** Purpose: Header for the cipher configuration of SQLite3 Multiple Ciphers 4 | ** Author: Ulrich Telle 5 | ** Created: 2020-03-10 6 | ** Copyright: (c) 2006-2020 Ulrich Telle 7 | ** License: MIT 8 | */ 9 | 10 | #ifndef CIPHER_CONFIG_H_ 11 | #define CIPHER_CONFIG_H_ 12 | 13 | #include "sqlite3mc.h" 14 | 15 | SQLITE_PRIVATE void sqlite3mcConfigTable(sqlite3_context* context, int argc, sqlite3_value** argv); 16 | SQLITE_PRIVATE CodecParameter* sqlite3mcGetCodecParams(sqlite3* db); 17 | 18 | /* Forward declaration */ 19 | static unsigned char* sqlite3mcGetSaltWriteCipher(Codec* codec); 20 | 21 | SQLITE_PRIVATE void sqlite3mcCodecDataSql(sqlite3_context* context, int argc, sqlite3_value** argv); 22 | SQLITE_PRIVATE void sqlite3mcConfigParams(sqlite3_context* context, int argc, sqlite3_value** argv); 23 | SQLITE_PRIVATE int sqlite3mcConfigureFromUri(sqlite3* db, const char *zDbName, int configDefault); 24 | 25 | SQLITE_PRIVATE int sqlite3mcFileControlPragma(sqlite3* db, const char* zDbName, int op, void* pArg); 26 | SQLITE_PRIVATE int sqlite3mcCodecQueryParameters(sqlite3* db, const char* zDb, const char* zUri); 27 | SQLITE_PRIVATE int sqlite3mcHandleAttachKey(sqlite3* db, const char* zName, const char* zPath, sqlite3_value* pKey, char** zErrDyn); 28 | SQLITE_PRIVATE int sqlite3mcHandleMainKey(sqlite3* db, const char* zPath); 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /wxsqlite3/cipher_sds_rc4.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Name: cipher_sds_rc4.c 3 | ** Purpose: Implementation of cipher System.Data.SQLite3 RC4 4 | ** Author: Ulrich Telle 5 | ** Created: 2020-02-02 6 | ** Copyright: (c) 2006-2020 Ulrich Telle 7 | ** License: MIT 8 | */ 9 | 10 | #include "cipher_common.h" 11 | 12 | /* --- RC4 cipher (System.Data.SQLite) --- */ 13 | #if HAVE_CIPHER_RC4 14 | 15 | /* 16 | ** Configuration parameters for "rc4" 17 | ** 18 | ** - legacy mode : compatibility with System.Data.SQLite encryption 19 | ** (page 1 fully encrypted) 20 | ** only legacy mode is supported 21 | ** possible value: 1 = yes 22 | */ 23 | 24 | #define RC4_LEGACY_DEFAULT 1 25 | 26 | SQLITE_PRIVATE CipherParams mcRC4Params[] = 27 | { 28 | { "legacy", RC4_LEGACY_DEFAULT, RC4_LEGACY_DEFAULT, RC4_LEGACY_DEFAULT, RC4_LEGACY_DEFAULT }, 29 | { "legacy_page_size", 0, 0, 0, SQLITE_MAX_PAGE_SIZE }, 30 | CIPHER_PARAMS_SENTINEL 31 | }; 32 | 33 | 34 | #define KEYLENGTH_RC4 16 35 | 36 | typedef struct _RC4Cipher 37 | { 38 | int m_legacy; 39 | int m_legacyPageSize; 40 | int m_keyLength; 41 | uint8_t m_key[KEYLENGTH_RC4]; 42 | } RC4Cipher; 43 | 44 | static void* 45 | AllocateRC4Cipher(sqlite3* db) 46 | { 47 | RC4Cipher* rc4Cipher = (RC4Cipher*) sqlite3_malloc(sizeof(RC4Cipher)); 48 | if (rc4Cipher != NULL) 49 | { 50 | rc4Cipher->m_keyLength = KEYLENGTH_RC4; 51 | memset(rc4Cipher->m_key, 0, KEYLENGTH_RC4); 52 | } 53 | if (rc4Cipher != NULL) 54 | { 55 | CipherParams* cipherParams = sqlite3mcGetCipherParams(db, CODEC_TYPE_RC4); 56 | rc4Cipher->m_legacy = sqlite3mcGetCipherParameter(cipherParams, "legacy"); 57 | rc4Cipher->m_legacyPageSize = sqlite3mcGetCipherParameter(cipherParams, "legacy_page_size"); 58 | } 59 | return rc4Cipher; 60 | } 61 | 62 | static void 63 | FreeRC4Cipher(void* cipher) 64 | { 65 | RC4Cipher* localCipher = (RC4Cipher*) cipher; 66 | memset(localCipher, 0, sizeof(RC4Cipher)); 67 | sqlite3_free(localCipher); 68 | } 69 | 70 | static void 71 | CloneRC4Cipher(void* cipherTo, void* cipherFrom) 72 | { 73 | RC4Cipher* rc4CipherTo = (RC4Cipher*) cipherTo; 74 | RC4Cipher* rc4CipherFrom = (RC4Cipher*) cipherFrom; 75 | rc4CipherTo->m_legacy = rc4CipherFrom->m_legacy; 76 | rc4CipherTo->m_legacyPageSize = rc4CipherFrom->m_legacyPageSize; 77 | rc4CipherTo->m_keyLength = rc4CipherFrom->m_keyLength; 78 | memcpy(rc4CipherTo->m_key, rc4CipherFrom->m_key, KEYLENGTH_RC4); 79 | } 80 | 81 | static int 82 | GetLegacyRC4Cipher(void* cipher) 83 | { 84 | RC4Cipher* rc4Cipher = (RC4Cipher*)cipher; 85 | return rc4Cipher->m_legacy; 86 | } 87 | 88 | static int 89 | GetPageSizeRC4Cipher(void* cipher) 90 | { 91 | RC4Cipher* rc4Cipher = (RC4Cipher*) cipher; 92 | int pageSize = 0; 93 | if (rc4Cipher->m_legacy != 0) 94 | { 95 | pageSize = rc4Cipher->m_legacyPageSize; 96 | if ((pageSize < 512) || (pageSize > SQLITE_MAX_PAGE_SIZE) || (((pageSize - 1) & pageSize) != 0)) 97 | { 98 | pageSize = 0; 99 | } 100 | } 101 | return pageSize; 102 | } 103 | 104 | static int 105 | GetReservedRC4Cipher(void* cipher) 106 | { 107 | return 0; 108 | } 109 | 110 | static unsigned char* 111 | GetSaltRC4Cipher(void* cipher) 112 | { 113 | return NULL; 114 | } 115 | 116 | static void 117 | GenerateKeyRC4Cipher(void* cipher, BtShared* pBt, char* userPassword, int passwordLength, int rekey, unsigned char* cipherSalt) 118 | { 119 | RC4Cipher* rc4Cipher = (RC4Cipher*) cipher; 120 | unsigned char digest[SHA1_DIGEST_SIZE]; 121 | sha1_ctx ctx; 122 | 123 | sha1_init(&ctx); 124 | sha1_update(&ctx, userPassword, passwordLength); 125 | sha1_final(&ctx, digest); 126 | 127 | memcpy(rc4Cipher->m_key, digest, 16); 128 | /* memset(rc4Cipher->m_key+5, 0, rc4Cipher->m_keyLength-5);*/ 129 | } 130 | 131 | static int 132 | EncryptPageRC4Cipher(void* cipher, int page, unsigned char* data, int len, int reserved) 133 | { 134 | RC4Cipher* rc4Cipher = (RC4Cipher*) cipher; 135 | int rc = SQLITE_OK; 136 | 137 | /* Use the legacy encryption scheme */ 138 | unsigned char* key = rc4Cipher->m_key; 139 | sqlite3mcRC4(key, rc4Cipher->m_keyLength, data, len, data); 140 | 141 | return rc; 142 | } 143 | 144 | static int 145 | DecryptPageRC4Cipher(void* cipher, int page, unsigned char* data, int len, int reserved, int hmacCheck) 146 | { 147 | RC4Cipher* rc4Cipher = (RC4Cipher*) cipher; 148 | int rc = SQLITE_OK; 149 | 150 | /* Use the legacy encryption scheme */ 151 | sqlite3mcRC4(rc4Cipher->m_key, rc4Cipher->m_keyLength, data, len, data); 152 | 153 | return rc; 154 | } 155 | 156 | SQLITE_PRIVATE const CipherDescriptor mcRC4Descriptor = 157 | { 158 | "rc4", AllocateRC4Cipher, 159 | FreeRC4Cipher, 160 | CloneRC4Cipher, 161 | GetLegacyRC4Cipher, 162 | GetPageSizeRC4Cipher, 163 | GetReservedRC4Cipher, 164 | GetSaltRC4Cipher, 165 | GenerateKeyRC4Cipher, 166 | EncryptPageRC4Cipher, 167 | DecryptPageRC4Cipher 168 | }; 169 | #endif 170 | -------------------------------------------------------------------------------- /wxsqlite3/cipher_wxaes128.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Name: cipher_wxaes128.c 3 | ** Purpose: Implementation of cipher wxSQLite3 AES 128-bit 4 | ** Author: Ulrich Telle 5 | ** Created: 2020-02-02 6 | ** Copyright: (c) 2006-2020 Ulrich Telle 7 | ** License: MIT 8 | */ 9 | 10 | #include "cipher_common.h" 11 | 12 | /* --- AES 128-bit cipher (wxSQLite3) --- */ 13 | #if HAVE_CIPHER_AES_128_CBC 14 | 15 | /* 16 | ** Configuration parameters for "aes128cbc" 17 | ** 18 | ** - legacy mode : compatibility with first version (page 1 encrypted) 19 | ** possible values: 1 = yes, 0 = no (default) 20 | */ 21 | 22 | #ifdef WXSQLITE3_USE_OLD_ENCRYPTION_SCHEME 23 | #define AES128_LEGACY_DEFAULT 1 24 | #else 25 | #define AES128_LEGACY_DEFAULT 0 26 | #endif 27 | 28 | SQLITE_PRIVATE CipherParams mcAES128Params[] = 29 | { 30 | { "legacy", AES128_LEGACY_DEFAULT, AES128_LEGACY_DEFAULT, 0, 1 }, 31 | { "legacy_page_size", 0, 0, 0, SQLITE_MAX_PAGE_SIZE }, 32 | CIPHER_PARAMS_SENTINEL 33 | }; 34 | 35 | typedef struct _AES128Cipher 36 | { 37 | int m_legacy; 38 | int m_legacyPageSize; 39 | int m_keyLength; 40 | uint8_t m_key[KEYLENGTH_AES128]; 41 | Rijndael* m_aes; 42 | } AES128Cipher; 43 | 44 | static void* 45 | AllocateAES128Cipher(sqlite3* db) 46 | { 47 | AES128Cipher* aesCipher = (AES128Cipher*) sqlite3_malloc(sizeof(AES128Cipher)); 48 | if (aesCipher != NULL) 49 | { 50 | aesCipher->m_aes = (Rijndael*) sqlite3_malloc(sizeof(Rijndael)); 51 | if (aesCipher->m_aes != NULL) 52 | { 53 | aesCipher->m_keyLength = KEYLENGTH_AES128; 54 | memset(aesCipher->m_key, 0, KEYLENGTH_AES128); 55 | RijndaelCreate(aesCipher->m_aes); 56 | } 57 | else 58 | { 59 | sqlite3_free(aesCipher); 60 | aesCipher = NULL; 61 | } 62 | } 63 | if (aesCipher != NULL) 64 | { 65 | CipherParams* cipherParams = sqlite3mcGetCipherParams(db, CODEC_TYPE_AES128); 66 | aesCipher->m_legacy = sqlite3mcGetCipherParameter(cipherParams, "legacy"); 67 | aesCipher->m_legacyPageSize = sqlite3mcGetCipherParameter(cipherParams, "legacy_page_size"); 68 | } 69 | return aesCipher; 70 | } 71 | 72 | static void 73 | FreeAES128Cipher(void* cipher) 74 | { 75 | AES128Cipher* localCipher = (AES128Cipher*) cipher; 76 | memset(localCipher->m_aes, 0, sizeof(Rijndael)); 77 | sqlite3_free(localCipher->m_aes); 78 | memset(localCipher, 0, sizeof(AES128Cipher)); 79 | sqlite3_free(localCipher); 80 | } 81 | 82 | static void 83 | CloneAES128Cipher(void* cipherTo, void* cipherFrom) 84 | { 85 | AES128Cipher* aesCipherTo = (AES128Cipher*) cipherTo; 86 | AES128Cipher* aesCipherFrom = (AES128Cipher*) cipherFrom; 87 | aesCipherTo->m_legacy = aesCipherFrom->m_legacy; 88 | aesCipherTo->m_legacyPageSize = aesCipherFrom->m_legacyPageSize; 89 | aesCipherTo->m_keyLength = aesCipherFrom->m_keyLength; 90 | memcpy(aesCipherTo->m_key, aesCipherFrom->m_key, KEYLENGTH_AES128); 91 | RijndaelInvalidate(aesCipherTo->m_aes); 92 | RijndaelInvalidate(aesCipherFrom->m_aes); 93 | } 94 | 95 | static int 96 | GetLegacyAES128Cipher(void* cipher) 97 | { 98 | AES128Cipher* aesCipher = (AES128Cipher*)cipher; 99 | return aesCipher->m_legacy; 100 | } 101 | 102 | static int 103 | GetPageSizeAES128Cipher(void* cipher) 104 | { 105 | AES128Cipher* aesCipher = (AES128Cipher*) cipher; 106 | int pageSize = 0; 107 | if (aesCipher->m_legacy != 0) 108 | { 109 | pageSize = aesCipher->m_legacyPageSize; 110 | if ((pageSize < 512) || (pageSize > SQLITE_MAX_PAGE_SIZE) || (((pageSize - 1) & pageSize) != 0)) 111 | { 112 | pageSize = 0; 113 | } 114 | } 115 | return pageSize; 116 | } 117 | 118 | static int 119 | GetReservedAES128Cipher(void* cipher) 120 | { 121 | return 0; 122 | } 123 | 124 | static unsigned char* 125 | GetSaltAES128Cipher(void* cipher) 126 | { 127 | return NULL; 128 | } 129 | 130 | static void 131 | GenerateKeyAES128Cipher(void* cipher, BtShared* pBt, char* userPassword, int passwordLength, int rekey, unsigned char* cipherSalt) 132 | { 133 | AES128Cipher* aesCipher = (AES128Cipher*) cipher; 134 | unsigned char userPad[32]; 135 | unsigned char ownerPad[32]; 136 | unsigned char ownerKey[32]; 137 | 138 | unsigned char mkey[MD5_HASHBYTES]; 139 | unsigned char digest[MD5_HASHBYTES]; 140 | int keyLength = MD5_HASHBYTES; 141 | int i, j, k; 142 | MD5_CTX ctx; 143 | 144 | /* Pad passwords */ 145 | sqlite3mcPadPassword(userPassword, passwordLength, userPad); 146 | sqlite3mcPadPassword("", 0, ownerPad); 147 | 148 | /* Compute owner key */ 149 | 150 | MD5_Init(&ctx); 151 | MD5_Update(&ctx, ownerPad, 32); 152 | MD5_Final(digest, &ctx); 153 | 154 | /* only use for the input as many bit as the key consists of */ 155 | for (k = 0; k < 50; ++k) 156 | { 157 | MD5_Init(&ctx); 158 | MD5_Update(&ctx, digest, keyLength); 159 | MD5_Final(digest, &ctx); 160 | } 161 | memcpy(ownerKey, userPad, 32); 162 | for (i = 0; i < 20; ++i) 163 | { 164 | for (j = 0; j < keyLength; ++j) 165 | { 166 | mkey[j] = (digest[j] ^ i); 167 | } 168 | sqlite3mcRC4(mkey, keyLength, ownerKey, 32, ownerKey); 169 | } 170 | 171 | /* Compute encryption key */ 172 | 173 | MD5_Init(&ctx); 174 | MD5_Update(&ctx, userPad, 32); 175 | MD5_Update(&ctx, ownerKey, 32); 176 | MD5_Final(digest, &ctx); 177 | 178 | /* only use the really needed bits as input for the hash */ 179 | for (k = 0; k < 50; ++k) 180 | { 181 | MD5_Init(&ctx); 182 | MD5_Update(&ctx, digest, keyLength); 183 | MD5_Final(digest, &ctx); 184 | } 185 | memcpy(aesCipher->m_key, digest, aesCipher->m_keyLength); 186 | } 187 | 188 | static int 189 | EncryptPageAES128Cipher(void* cipher, int page, unsigned char* data, int len, int reserved) 190 | { 191 | AES128Cipher* aesCipher = (AES128Cipher*) cipher; 192 | int rc = SQLITE_OK; 193 | if (aesCipher->m_legacy != 0) 194 | { 195 | /* Use the legacy encryption scheme */ 196 | unsigned char* key = aesCipher->m_key; 197 | rc = sqlite3mcAES128(aesCipher->m_aes, page, 1, key, data, len, data); 198 | } 199 | else 200 | { 201 | unsigned char dbHeader[8]; 202 | int offset = 0; 203 | unsigned char* key = aesCipher->m_key; 204 | if (page == 1) 205 | { 206 | /* Save the header bytes remaining unencrypted */ 207 | memcpy(dbHeader, data + 16, 8); 208 | offset = 16; 209 | sqlite3mcAES128(aesCipher->m_aes, page, 1, key, data, 16, data); 210 | } 211 | rc = sqlite3mcAES128(aesCipher->m_aes, page, 1, key, data + offset, len - offset, data + offset); 212 | if (page == 1) 213 | { 214 | /* Move the encrypted header bytes 16..23 to a safe position */ 215 | memcpy(data + 8, data + 16, 8); 216 | /* Restore the unencrypted header bytes 16..23 */ 217 | memcpy(data + 16, dbHeader, 8); 218 | } 219 | } 220 | return rc; 221 | } 222 | 223 | static int 224 | DecryptPageAES128Cipher(void* cipher, int page, unsigned char* data, int len, int reserved, int hmacCheck) 225 | { 226 | AES128Cipher* aesCipher = (AES128Cipher*) cipher; 227 | int rc = SQLITE_OK; 228 | if (aesCipher->m_legacy != 0) 229 | { 230 | /* Use the legacy encryption scheme */ 231 | rc = sqlite3mcAES128(aesCipher->m_aes, page, 0, aesCipher->m_key, data, len, data); 232 | } 233 | else 234 | { 235 | unsigned char dbHeader[8]; 236 | int dbPageSize; 237 | int offset = 0; 238 | if (page == 1) 239 | { 240 | /* Save (unencrypted) header bytes 16..23 */ 241 | memcpy(dbHeader, data + 16, 8); 242 | /* Determine page size */ 243 | dbPageSize = (dbHeader[0] << 8) | (dbHeader[1] << 16); 244 | /* Check whether the database header is valid */ 245 | /* If yes, the database follows the new encryption scheme, otherwise use the previous encryption scheme */ 246 | if ((dbPageSize >= 512) && (dbPageSize <= SQLITE_MAX_PAGE_SIZE) && (((dbPageSize - 1) & dbPageSize) == 0) && 247 | (dbHeader[5] == 0x40) && (dbHeader[6] == 0x20) && (dbHeader[7] == 0x20)) 248 | { 249 | /* Restore encrypted bytes 16..23 for new encryption scheme */ 250 | memcpy(data + 16, data + 8, 8); 251 | offset = 16; 252 | } 253 | } 254 | rc = sqlite3mcAES128(aesCipher->m_aes, page, 0, aesCipher->m_key, data + offset, len - offset, data + offset); 255 | if (page == 1 && offset != 0) 256 | { 257 | /* Verify the database header */ 258 | if (memcmp(dbHeader, data + 16, 8) == 0) 259 | { 260 | memcpy(data, SQLITE_FILE_HEADER, 16); 261 | } 262 | } 263 | } 264 | return rc; 265 | } 266 | 267 | SQLITE_PRIVATE const CipherDescriptor mcAES128Descriptor = 268 | { 269 | "aes128cbc", AllocateAES128Cipher, 270 | FreeAES128Cipher, 271 | CloneAES128Cipher, 272 | GetLegacyAES128Cipher, 273 | GetPageSizeAES128Cipher, 274 | GetReservedAES128Cipher, 275 | GetSaltAES128Cipher, 276 | GenerateKeyAES128Cipher, 277 | EncryptPageAES128Cipher, 278 | DecryptPageAES128Cipher 279 | }; 280 | #endif 281 | -------------------------------------------------------------------------------- /wxsqlite3/cipher_wxaes256.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Name: cipher_wxaes256.c 3 | ** Purpose: Implementation of cipher wxSQLite3 AES 256-bit 4 | ** Author: Ulrich Telle 5 | ** Created: 2020-02-02 6 | ** Copyright: (c) 2006-2020 Ulrich Telle 7 | ** License: MIT 8 | */ 9 | 10 | #include "cipher_common.h" 11 | 12 | /* --- AES 256-bit cipher (wxSQLite3) --- */ 13 | #if HAVE_CIPHER_AES_256_CBC 14 | 15 | /* 16 | ** Configuration parameters for "aes256cbc" 17 | ** 18 | ** - legacy mode : compatibility with first version (page 1 encrypted) 19 | ** possible values: 1 = yes, 0 = no (default) 20 | ** - kdf_iter : number of iterations for key derivation 21 | */ 22 | 23 | #ifdef WXSQLITE3_USE_OLD_ENCRYPTION_SCHEME 24 | #define AES256_LEGACY_DEFAULT 1 25 | #else 26 | #define AES256_LEGACY_DEFAULT 0 27 | #endif 28 | 29 | SQLITE_PRIVATE CipherParams mcAES256Params[] = 30 | { 31 | { "legacy", AES256_LEGACY_DEFAULT, AES256_LEGACY_DEFAULT, 0, 1 }, 32 | { "legacy_page_size", 0, 0, 0, SQLITE_MAX_PAGE_SIZE }, 33 | { "kdf_iter", CODEC_SHA_ITER, CODEC_SHA_ITER, 1, 0x7fffffff }, 34 | CIPHER_PARAMS_SENTINEL 35 | }; 36 | 37 | 38 | typedef struct _AES256Cipher 39 | { 40 | int m_legacy; 41 | int m_legacyPageSize; 42 | int m_kdfIter; 43 | int m_keyLength; 44 | uint8_t m_key[KEYLENGTH_AES256]; 45 | Rijndael* m_aes; 46 | } AES256Cipher; 47 | 48 | static void* 49 | AllocateAES256Cipher(sqlite3* db) 50 | { 51 | AES256Cipher* aesCipher = (AES256Cipher*) sqlite3_malloc(sizeof(AES256Cipher)); 52 | if (aesCipher != NULL) 53 | { 54 | aesCipher->m_aes = (Rijndael*) sqlite3_malloc(sizeof(Rijndael)); 55 | if (aesCipher->m_aes != NULL) 56 | { 57 | aesCipher->m_keyLength = KEYLENGTH_AES256; 58 | memset(aesCipher->m_key, 0, KEYLENGTH_AES256); 59 | RijndaelCreate(aesCipher->m_aes); 60 | } 61 | else 62 | { 63 | sqlite3_free(aesCipher); 64 | aesCipher = NULL; 65 | } 66 | } 67 | if (aesCipher != NULL) 68 | { 69 | CipherParams* cipherParams = sqlite3mcGetCipherParams(db, CODEC_TYPE_AES256); 70 | aesCipher->m_legacy = sqlite3mcGetCipherParameter(cipherParams, "legacy"); 71 | aesCipher->m_legacyPageSize = sqlite3mcGetCipherParameter(cipherParams, "legacy_page_size"); 72 | aesCipher->m_kdfIter = sqlite3mcGetCipherParameter(cipherParams, "kdf_iter"); 73 | } 74 | return aesCipher; 75 | } 76 | 77 | static void 78 | FreeAES256Cipher(void* cipher) 79 | { 80 | AES256Cipher* aesCipher = (AES256Cipher*) cipher; 81 | memset(aesCipher->m_aes, 0, sizeof(Rijndael)); 82 | sqlite3_free(aesCipher->m_aes); 83 | memset(aesCipher, 0, sizeof(AES256Cipher)); 84 | sqlite3_free(aesCipher); 85 | } 86 | 87 | static void 88 | CloneAES256Cipher(void* cipherTo, void* cipherFrom) 89 | { 90 | AES256Cipher* aesCipherTo = (AES256Cipher*) cipherTo; 91 | AES256Cipher* aesCipherFrom = (AES256Cipher*) cipherFrom; 92 | aesCipherTo->m_legacy = aesCipherFrom->m_legacy; 93 | aesCipherTo->m_legacyPageSize = aesCipherFrom->m_legacyPageSize; 94 | aesCipherTo->m_kdfIter = aesCipherFrom->m_kdfIter; 95 | aesCipherTo->m_keyLength = aesCipherFrom->m_keyLength; 96 | memcpy(aesCipherTo->m_key, aesCipherFrom->m_key, KEYLENGTH_AES256); 97 | RijndaelInvalidate(aesCipherTo->m_aes); 98 | RijndaelInvalidate(aesCipherFrom->m_aes); 99 | } 100 | 101 | static int 102 | GetLegacyAES256Cipher(void* cipher) 103 | { 104 | AES256Cipher* aesCipher = (AES256Cipher*)cipher; 105 | return aesCipher->m_legacy; 106 | } 107 | 108 | static int 109 | GetPageSizeAES256Cipher(void* cipher) 110 | { 111 | AES256Cipher* aesCipher = (AES256Cipher*) cipher; 112 | int pageSize = 0; 113 | if (aesCipher->m_legacy != 0) 114 | { 115 | pageSize = aesCipher->m_legacyPageSize; 116 | if ((pageSize < 512) || (pageSize > SQLITE_MAX_PAGE_SIZE) || (((pageSize - 1) & pageSize) != 0)) 117 | { 118 | pageSize = 0; 119 | } 120 | } 121 | return pageSize; 122 | } 123 | 124 | static int 125 | GetReservedAES256Cipher(void* cipher) 126 | { 127 | return 0; 128 | } 129 | 130 | static unsigned char* 131 | GetSaltAES256Cipher(void* cipher) 132 | { 133 | return NULL; 134 | } 135 | 136 | static void 137 | GenerateKeyAES256Cipher(void* cipher, BtShared* pBt, char* userPassword, int passwordLength, int rekey, unsigned char* cipherSalt) 138 | { 139 | AES256Cipher* aesCipher = (AES256Cipher*) cipher; 140 | unsigned char userPad[32]; 141 | unsigned char digest[KEYLENGTH_AES256]; 142 | int keyLength = KEYLENGTH_AES256; 143 | int k; 144 | 145 | /* Pad password */ 146 | sqlite3mcPadPassword(userPassword, passwordLength, userPad); 147 | 148 | sha256(userPad, 32, digest); 149 | for (k = 0; k < CODEC_SHA_ITER; ++k) 150 | { 151 | sha256(digest, KEYLENGTH_AES256, digest); 152 | } 153 | memcpy(aesCipher->m_key, digest, aesCipher->m_keyLength); 154 | } 155 | 156 | static int 157 | EncryptPageAES256Cipher(void* cipher, int page, unsigned char* data, int len, int reserved) 158 | { 159 | AES256Cipher* aesCipher = (AES256Cipher*) cipher; 160 | int rc = SQLITE_OK; 161 | if (aesCipher->m_legacy != 0) 162 | { 163 | /* Use the legacy encryption scheme */ 164 | unsigned char* key = aesCipher->m_key; 165 | rc = sqlite3mcAES256(aesCipher->m_aes, page, 1, key, data, len, data); 166 | } 167 | else 168 | { 169 | unsigned char dbHeader[8]; 170 | int offset = 0; 171 | unsigned char* key = aesCipher->m_key; 172 | if (page == 1) 173 | { 174 | /* Save the header bytes remaining unencrypted */ 175 | memcpy(dbHeader, data + 16, 8); 176 | offset = 16; 177 | sqlite3mcAES256(aesCipher->m_aes, page, 1, key, data, 16, data); 178 | } 179 | rc = sqlite3mcAES256(aesCipher->m_aes, page, 1, key, data + offset, len - offset, data + offset); 180 | if (page == 1) 181 | { 182 | /* Move the encrypted header bytes 16..23 to a safe position */ 183 | memcpy(data + 8, data + 16, 8); 184 | /* Restore the unencrypted header bytes 16..23 */ 185 | memcpy(data + 16, dbHeader, 8); 186 | } 187 | } 188 | return rc; 189 | } 190 | 191 | static int 192 | DecryptPageAES256Cipher(void* cipher, int page, unsigned char* data, int len, int reserved, int hmacCheck) 193 | { 194 | AES256Cipher* aesCipher = (AES256Cipher*) cipher; 195 | int rc = SQLITE_OK; 196 | if (aesCipher->m_legacy != 0) 197 | { 198 | /* Use the legacy encryption scheme */ 199 | rc = sqlite3mcAES256(aesCipher->m_aes, page, 0, aesCipher->m_key, data, len, data); 200 | } 201 | else 202 | { 203 | unsigned char dbHeader[8]; 204 | int dbPageSize; 205 | int offset = 0; 206 | if (page == 1) 207 | { 208 | /* Save (unencrypted) header bytes 16..23 */ 209 | memcpy(dbHeader, data + 16, 8); 210 | /* Determine page size */ 211 | dbPageSize = (dbHeader[0] << 8) | (dbHeader[1] << 16); 212 | /* Check whether the database header is valid */ 213 | /* If yes, the database follows the new encryption scheme, otherwise use the previous encryption scheme */ 214 | if ((dbPageSize >= 512) && (dbPageSize <= SQLITE_MAX_PAGE_SIZE) && (((dbPageSize - 1) & dbPageSize) == 0) && 215 | (dbHeader[5] == 0x40) && (dbHeader[6] == 0x20) && (dbHeader[7] == 0x20)) 216 | { 217 | /* Restore encrypted bytes 16..23 for new encryption scheme */ 218 | memcpy(data + 16, data + 8, 8); 219 | offset = 16; 220 | } 221 | } 222 | rc = sqlite3mcAES256(aesCipher->m_aes, page, 0, aesCipher->m_key, data + offset, len - offset, data + offset); 223 | if (page == 1 && offset != 0) 224 | { 225 | /* Verify the database header */ 226 | if (memcmp(dbHeader, data + 16, 8) == 0) 227 | { 228 | memcpy(data, SQLITE_FILE_HEADER, 16); 229 | } 230 | } 231 | } 232 | return rc; 233 | } 234 | 235 | SQLITE_PRIVATE const CipherDescriptor mcAES256Descriptor = 236 | { 237 | "aes256cbc", AllocateAES256Cipher, 238 | FreeAES256Cipher, 239 | CloneAES256Cipher, 240 | GetLegacyAES256Cipher, 241 | GetPageSizeAES256Cipher, 242 | GetReservedAES256Cipher, 243 | GetSaltAES256Cipher, 244 | GenerateKeyAES256Cipher, 245 | EncryptPageAES256Cipher, 246 | DecryptPageAES256Cipher 247 | }; 248 | #endif 249 | -------------------------------------------------------------------------------- /wxsqlite3/codec_algos.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Name: codec_algos.c 3 | ** Purpose: Implementation of SQLite codec algorithms 4 | ** Author: Ulrich Telle 5 | ** Created: 2020-02-02 6 | ** Copyright: (c) 2006-2020 Ulrich Telle 7 | ** License: MIT 8 | */ 9 | 10 | #include "cipher_common.h" 11 | #if HAVE_CIPHER_AES_128_CBC || HAVE_CIPHER_AES_256_CBC || HAVE_CIPHER_SQLCIPHER 12 | #include "rijndael.h" 13 | #endif 14 | 15 | /* 16 | ** RC4 implementation 17 | */ 18 | 19 | SQLITE_PRIVATE void 20 | sqlite3mcRC4(unsigned char* key, int keylen, 21 | unsigned char* textin, int textlen, 22 | unsigned char* textout) 23 | { 24 | int i; 25 | int j; 26 | int t; 27 | unsigned char rc4[256]; 28 | 29 | int a = 0; 30 | int b = 0; 31 | unsigned char k; 32 | 33 | for (i = 0; i < 256; i++) 34 | { 35 | rc4[i] = i; 36 | } 37 | j = 0; 38 | for (i = 0; i < 256; i++) 39 | { 40 | t = rc4[i]; 41 | j = (j + t + key[i % keylen]) % 256; 42 | rc4[i] = rc4[j]; 43 | rc4[j] = t; 44 | } 45 | 46 | for (i = 0; i < textlen; i++) 47 | { 48 | a = (a + 1) % 256; 49 | t = rc4[a]; 50 | b = (b + t) % 256; 51 | rc4[a] = rc4[b]; 52 | rc4[b] = t; 53 | k = rc4[(rc4[a] + rc4[b]) % 256]; 54 | textout[i] = textin[i] ^ k; 55 | } 56 | } 57 | 58 | SQLITE_PRIVATE void 59 | sqlite3mcGetMD5Binary(unsigned char* data, int length, unsigned char* digest) 60 | { 61 | MD5_CTX ctx; 62 | MD5_Init(&ctx); 63 | MD5_Update(&ctx, data, length); 64 | MD5_Final(digest,&ctx); 65 | } 66 | 67 | SQLITE_PRIVATE void 68 | sqlite3mcGetSHABinary(unsigned char* data, int length, unsigned char* digest) 69 | { 70 | sha256(data, (unsigned int) length, digest); 71 | } 72 | 73 | #define MODMULT(a, b, c, m, s) q = s / a; s = b * (s - a * q) - c * q; if (s < 0) s += m 74 | 75 | SQLITE_PRIVATE void 76 | sqlite3mcGenerateInitialVector(int seed, unsigned char iv[16]) 77 | { 78 | unsigned char initkey[16]; 79 | int j, q; 80 | int z = seed + 1; 81 | for (j = 0; j < 4; j++) 82 | { 83 | MODMULT(52774, 40692, 3791, 2147483399L, z); 84 | initkey[4*j+0] = 0xff & z; 85 | initkey[4*j+1] = 0xff & (z >> 8); 86 | initkey[4*j+2] = 0xff & (z >> 16); 87 | initkey[4*j+3] = 0xff & (z >> 24); 88 | } 89 | sqlite3mcGetMD5Binary((unsigned char*) initkey, 16, iv); 90 | } 91 | 92 | #if HAVE_CIPHER_AES_128_CBC 93 | 94 | SQLITE_PRIVATE int 95 | sqlite3mcAES128(Rijndael* aesCtx, int page, int encrypt, unsigned char encryptionKey[KEYLENGTH_AES128], 96 | unsigned char* datain, int datalen, unsigned char* dataout) 97 | { 98 | int rc = SQLITE_OK; 99 | unsigned char initial[16]; 100 | unsigned char pagekey[KEYLENGTH_AES128]; 101 | unsigned char nkey[KEYLENGTH_AES128+4+4]; 102 | int keyLength = KEYLENGTH_AES128; 103 | int nkeylen = keyLength + 4 + 4; 104 | int j; 105 | int direction = (encrypt) ? RIJNDAEL_Direction_Encrypt : RIJNDAEL_Direction_Decrypt; 106 | int len = 0; 107 | 108 | for (j = 0; j < keyLength; j++) 109 | { 110 | nkey[j] = encryptionKey[j]; 111 | } 112 | nkey[keyLength+0] = 0xff & page; 113 | nkey[keyLength+1] = 0xff & (page >> 8); 114 | nkey[keyLength+2] = 0xff & (page >> 16); 115 | nkey[keyLength+3] = 0xff & (page >> 24); 116 | 117 | /* AES encryption needs some 'salt' */ 118 | nkey[keyLength+4] = 0x73; 119 | nkey[keyLength+5] = 0x41; 120 | nkey[keyLength+6] = 0x6c; 121 | nkey[keyLength+7] = 0x54; 122 | 123 | sqlite3mcGetMD5Binary(nkey, nkeylen, pagekey); 124 | sqlite3mcGenerateInitialVector(page, initial); 125 | RijndaelInit(aesCtx, RIJNDAEL_Direction_Mode_CBC, direction, pagekey, RIJNDAEL_Direction_KeyLength_Key16Bytes, initial); 126 | if (encrypt) 127 | { 128 | len = RijndaelBlockEncrypt(aesCtx, datain, datalen*8, dataout); 129 | } 130 | else 131 | { 132 | len = RijndaelBlockDecrypt(aesCtx, datain, datalen*8, dataout); 133 | } 134 | 135 | /* It is a good idea to check the error code */ 136 | if (len < 0) 137 | { 138 | /* AES: Error on encrypting. */ 139 | rc = SQLITE_ERROR; 140 | } 141 | return rc; 142 | } 143 | 144 | #endif 145 | 146 | #if HAVE_CIPHER_AES_256_CBC 147 | 148 | SQLITE_PRIVATE int 149 | sqlite3mcAES256(Rijndael* aesCtx, int page, int encrypt, unsigned char encryptionKey[KEYLENGTH_AES256], 150 | unsigned char* datain, int datalen, unsigned char* dataout) 151 | { 152 | int rc = SQLITE_OK; 153 | unsigned char initial[16]; 154 | unsigned char pagekey[KEYLENGTH_AES256]; 155 | unsigned char nkey[KEYLENGTH_AES256+4+4]; 156 | int keyLength = KEYLENGTH_AES256; 157 | int nkeylen = keyLength + 4 + 4; 158 | int j; 159 | int direction = (encrypt) ? RIJNDAEL_Direction_Encrypt : RIJNDAEL_Direction_Decrypt; 160 | int len = 0; 161 | 162 | for (j = 0; j < keyLength; j++) 163 | { 164 | nkey[j] = encryptionKey[j]; 165 | } 166 | nkey[keyLength+0] = 0xff & page; 167 | nkey[keyLength+1] = 0xff & (page >> 8); 168 | nkey[keyLength+2] = 0xff & (page >> 16); 169 | nkey[keyLength+3] = 0xff & (page >> 24); 170 | 171 | /* AES encryption needs some 'salt' */ 172 | nkey[keyLength+4] = 0x73; 173 | nkey[keyLength+5] = 0x41; 174 | nkey[keyLength+6] = 0x6c; 175 | nkey[keyLength+7] = 0x54; 176 | 177 | sqlite3mcGetSHABinary(nkey, nkeylen, pagekey); 178 | sqlite3mcGenerateInitialVector(page, initial); 179 | RijndaelInit(aesCtx, RIJNDAEL_Direction_Mode_CBC, direction, pagekey, RIJNDAEL_Direction_KeyLength_Key32Bytes, initial); 180 | if (encrypt) 181 | { 182 | len = RijndaelBlockEncrypt(aesCtx, datain, datalen*8, dataout); 183 | } 184 | else 185 | { 186 | len = RijndaelBlockDecrypt(aesCtx, datain, datalen*8, dataout); 187 | } 188 | 189 | /* It is a good idea to check the error code */ 190 | if (len < 0) 191 | { 192 | /* AES: Error on encrypting. */ 193 | rc = SQLITE_ERROR; 194 | } 195 | return rc; 196 | } 197 | 198 | #endif 199 | 200 | /* Check hex encoding */ 201 | SQLITE_PRIVATE int 202 | sqlite3mcIsHexKey(const unsigned char* hex, int len) 203 | { 204 | int j; 205 | for (j = 0; j < len; ++j) 206 | { 207 | unsigned char c = hex[j]; 208 | if ((c < '0' || c > '9') && (c < 'A' || c > 'F') && (c < 'a' || c > 'f')) 209 | { 210 | return 0; 211 | } 212 | } 213 | return 1; 214 | } 215 | 216 | /* Convert single hex digit */ 217 | SQLITE_PRIVATE int 218 | sqlite3mcConvertHex2Int(char c) 219 | { 220 | return (c >= '0' && c <= '9') ? (c)-'0' : 221 | (c >= 'A' && c <= 'F') ? (c)-'A' + 10 : 222 | (c >= 'a' && c <= 'f') ? (c)-'a' + 10 : 0; 223 | } 224 | 225 | /* Convert hex encoded string to binary */ 226 | SQLITE_PRIVATE void 227 | sqlite3mcConvertHex2Bin(const unsigned char* hex, int len, unsigned char* bin) 228 | { 229 | int j; 230 | for (j = 0; j < len; j += 2) 231 | { 232 | bin[j / 2] = (sqlite3mcConvertHex2Int(hex[j]) << 4) | sqlite3mcConvertHex2Int(hex[j + 1]); 233 | } 234 | } 235 | -------------------------------------------------------------------------------- /wxsqlite3/fastpbkdf2.h: -------------------------------------------------------------------------------- 1 | /* 2 | * fastpbkdf2 - Faster PBKDF2-HMAC calculation 3 | * Written in 2015 by Joseph Birr-Pixton 4 | * 5 | * To the extent possible under law, the author(s) have dedicated all 6 | * copyright and related and neighboring rights to this software to the 7 | * public domain worldwide. This software is distributed without any 8 | * warranty. 9 | * 10 | * You should have received a copy of the CC0 Public Domain Dedication 11 | * along with this software. If not, see 12 | * . 13 | */ 14 | 15 | #ifndef FASTPBKDF2_H 16 | #define FASTPBKDF2_H 17 | 18 | #include 19 | #include "mystdint.h" 20 | 21 | #ifdef __cplusplus 22 | extern "C" { 23 | #endif 24 | 25 | /** Calculates PBKDF2-HMAC-SHA1. 26 | * 27 | * @p npw bytes at @p pw are the password input. 28 | * @p nsalt bytes at @p salt are the salt input. 29 | * @p iterations is the PBKDF2 iteration count and must be non-zero. 30 | * @p nout bytes of output are written to @p out. @p nout must be non-zero. 31 | * 32 | * This function cannot fail; it does not report errors. 33 | */ 34 | void fastpbkdf2_hmac_sha1(const uint8_t *pw, size_t npw, 35 | const uint8_t *salt, size_t nsalt, 36 | uint32_t iterations, 37 | uint8_t *out, size_t nout); 38 | 39 | /** Calculates PBKDF2-HMAC-SHA256. 40 | * 41 | * @p npw bytes at @p pw are the password input. 42 | * @p nsalt bytes at @p salt are the salt input. 43 | * @p iterations is the PBKDF2 iteration count and must be non-zero. 44 | * @p nout bytes of output are written to @p out. @p nout must be non-zero. 45 | * 46 | * This function cannot fail; it does not report errors. 47 | */ 48 | void fastpbkdf2_hmac_sha256(const uint8_t *pw, size_t npw, 49 | const uint8_t *salt, size_t nsalt, 50 | uint32_t iterations, 51 | uint8_t *out, size_t nout); 52 | 53 | /** Calculates PBKDF2-HMAC-SHA512. 54 | * 55 | * @p npw bytes at @p pw are the password input. 56 | * @p nsalt bytes at @p salt are the salt input. 57 | * @p iterations is the PBKDF2 iteration count and must be non-zero. 58 | * @p nout bytes of output are written to @p out. @p nout must be non-zero. 59 | * 60 | * This function cannot fail; it does not report errors. 61 | */ 62 | void fastpbkdf2_hmac_sha512(const uint8_t *pw, size_t npw, 63 | const uint8_t *salt, size_t nsalt, 64 | uint32_t iterations, 65 | uint8_t *out, size_t nout); 66 | 67 | /** Calculates SQLCipher HMAC. 68 | * 69 | * This function cannot fail; it does not report errors. 70 | */ 71 | void sqlcipher_hmac(int algorithm, 72 | unsigned char* key, int nkey, 73 | unsigned char* in, int in_sz, 74 | unsigned char* in2, int in2_sz, 75 | unsigned char* out); 76 | 77 | #ifdef __cplusplus 78 | } 79 | #endif 80 | 81 | #endif 82 | -------------------------------------------------------------------------------- /wxsqlite3/filelist.md: -------------------------------------------------------------------------------- 1 | # Source files of the wxSQLite3 encryption extension 2 | 3 | The following document gives a short overview of all source files of which the **SQLite3 Multiple Ciphers** encryption extension consists. 4 | 5 | ## Kernel of the wxSQLite3 encryption extension 6 | 7 | The following files constitute the kernel of the **SQLite3 Multiple Ciphers** encryption extension: 8 | 9 | | Filename | Description | 10 | | :--- | :--- | 11 | | cipher_common.c | Implementation of the common cipher functions | 12 | | cipher_common.h | Header for the common cipher functions | 13 | | cipher_config.c | Common cipher configuration functions | 14 | | cipher_wxaes128.c | Implementation of the **wxSQLite3 AES 128-bit** encryption extension | 15 | | cipher_wxaes256.c | Implementation of the **wxSQLite3 AES 256-bit** encryption extension | 16 | | cipher_chacha20.c | Implementation of the **ChaCha20-Poly1305** encryption extension | 17 | | cipher_sqlcipher.c | Implementation of the **SQLCipher** encryption extension | 18 | | cipher_sds_rc4.c | Implementation of the **System.Data.SQLite RC4** encryption extension | 19 | | codec_algos.c | Implementation of the encryption algorithms | 20 | | codecext.c | Implementation of the **SQLite3** codec API | 21 | | rekeyvacuum.c | Adjusted VACUUM function for use on rekeying a database file | 22 | | sqlite3mc.c | _Amalgamation_ of the complete **SQLite3 Multiple Ciphers** encryption extension | 23 | | sqlite3mc.h | Header for the additional API functions of the **SQLite3 Multiple Ciphers** encryption extension | 24 | | sqlite3mc_vfs.c | Implementation of the Multiple Ciphers VFS | 25 | | sqlite3mc_vfs.h | Header for the additional API functions of the Multiple Ciphers VFS | 26 | 27 | All files, except `rekeyvacuum.c`, are licensed under the `MIT` license. 28 | 29 | `rekeyvacuum.c` contains a slightly modified implementation of the function `sqlite3RunVacuum` from the **SQLite3** and stays in the public domain. 30 | 31 | ## Cryptograhic algorithms 32 | 33 | The following files contain the implementations of cryptographic algorithms used by the **wxSQLite3** encryption extension: 34 | 35 | | Filename | Description | 36 | | :--- | :--- | 37 | | chacha20poly1305.c | Implementation of ChaCha20 cipher and Poly1305 message authentication | 38 | | fastpbkdf2.c | Implementation of PBKDF2 functions | 39 | | fastpbkdf2.h | Header for PBKDF2 functions | 40 | | md5.c | Implementation of MD5 hash functions | 41 | | rijndael.c | Implementation of AES block cipher | 42 | | rijndael.h | Header for AES block cipher | 43 | | sha1.c | Implementation of SHA1 hash functions | 44 | | sha1.h | Header for SHA1 hash functions | 45 | | sha2.c | Implementation of SHA2 hash functions | 46 | | sha2.h | Header for SHA2 hash functions | 47 | 48 | The files `chacha20poly1305.c`, `fastpbkdf2.*`, `md5.c`, and `sha1.*` are in the public domain. 49 | 50 | The files `rijndael.*`, are licensed under `LGPL-3.0+ WITH WxWindows-exception-3.1`. 51 | 52 | The files `sha2.*` are licensed under `BSD-3-Clause`. 53 | 54 | ## Windows-specific files 55 | 56 | The following files are only used under Windows platforms for creating binaries: 57 | 58 | | Filename | Description | 59 | | :--- | :--- | 60 | | sqlite3mc.def | Module definition specifying exported functions | 61 | | sqlite3mc.rc | Resource file specifying version information for the SQLite3MultipleCiphers library | 62 | | sqlite3mc_shell.rc | Resource file specifying version information for the SQLite3MultipleCiphers shell | 63 | 64 | All files are licensed under the `MIT` license. 65 | 66 | ## SQLite3 core 67 | 68 | The following files belong to the **SQLite3** core: 69 | 70 | | Filename | Description | 71 | | :--- | :--- | 72 | | shell.c | SQLite3 shell application | 73 | | sqlite3.c | SQLite3 source amalgamation | 74 | | sqlite3.h | SQLite3 header | 75 | | sqlite3ext.h | SQLite3 header for extensions | 76 | | test_windirent.c | Source for directory access under Windows used by `fileio` extension | 77 | | test_windirent.h | Header for directory access under Windows used by `fileio` extension | 78 | 79 | All files are in the public domain. 80 | 81 | ## SQLite3 extensions 82 | 83 | The following files belong to **SQLite3** extensions contained in the official **SQLite3** distribution: 84 | 85 | | Filename | Description | 86 | | :--- | :--- | 87 | | carray.c | Table-valued function that returns the values in a C-language array | 88 | | csv.c | Virtual table for reading CSV files | 89 | | fileio.c | Functions `readfile` and `writefile`, and eponymous virtual table `fsdir` | 90 | | series.c | Table-valued-function implementing the function `generate_series` | 91 | | shathree.c | Functions computing SHA3 hashes | 92 | | sqlite3userauth.h | Header for user-authentication extension feature | 93 | | userauth.c | User-authentication extension feature (modified password hash function) | 94 | | uuid.c | Functions handling RFC-4122 UUIDs | 95 | 96 | All files are in the public domain. 97 | 98 | ## External SQLite3 extensions 99 | 100 | The following file was posted to the SQLite mailing list: 101 | 102 | | Filename | Description | 103 | | :--- | :--- | 104 | | extensionfunctions.c | The extension provides common mathematical and string functions | 105 | 106 | The file `extensionfunctions.c` does not contain any specific license information. Since it was posted to the SQLite mailing list, it is assumed that the file is in the public domain like SQLite3 itself. 107 | -------------------------------------------------------------------------------- /wxsqlite3/mystdint.h: -------------------------------------------------------------------------------- 1 | #ifndef MY_STDINT_H_ 2 | #define MY_STDINT_H_ 3 | 4 | /* 5 | ** MS Visual C++ 2008 and below do not provide the header file 6 | ** That is, we need to define the necessary types ourselves 7 | */ 8 | 9 | #if defined(_MSC_VER) && (_MSC_VER < 1600) 10 | typedef signed char int8_t; 11 | typedef short int16_t; 12 | typedef int int32_t; 13 | typedef long long int64_t; 14 | typedef unsigned char uint8_t; 15 | typedef unsigned short uint16_t; 16 | typedef unsigned int uint32_t; 17 | typedef unsigned long long uint64_t; 18 | 19 | #define UINT8_MAX 255 20 | #define UINT16_MAX 65535 21 | #define UINT32_MAX 0xffffffffU /* 4294967295U */ 22 | #define UINT64_MAX 0xffffffffffffffffULL /* 18446744073709551615ULL */ 23 | #else 24 | #include 25 | #endif 26 | 27 | #endif /* MY_STDINT_H_ */ 28 | -------------------------------------------------------------------------------- /wxsqlite3/rijndael.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Name: rijndael.h 3 | ** Purpose: Header file for the Rijndael cipher 4 | ** Author: Ulrich Telle 5 | ** Created: 2006-12-06 6 | ** Copyright: (c) 2006-2020 Ulrich Telle 7 | ** License: MIT 8 | ** 9 | ** Adjustments were made to make this code work with the wxSQLite3's 10 | ** SQLite encryption extension. 11 | ** The original code is public domain (see comments below). 12 | */ 13 | 14 | /* 15 | /// \file rijndael.h Interface of the Rijndael cipher 16 | */ 17 | 18 | #ifndef _RIJNDAEL_H_ 19 | #define _RIJNDAEL_H_ 20 | 21 | /* 22 | // File : rijndael.h 23 | // Creation date : Sun Nov 5 2000 03:21:05 CEST 24 | // Author : Szymon Stefanek (stefanek@tin.it) 25 | // 26 | // Another implementation of the Rijndael cipher. 27 | // This is intended to be an easily usable library file. 28 | // This code is public domain. 29 | // Based on the Vincent Rijmen and K.U.Leuven implementation 2.4. 30 | // 31 | // Original Copyright notice: 32 | // 33 | // rijndael-alg-fst.c v2.4 April '2000 34 | // rijndael-alg-fst.h 35 | // rijndael-api-fst.c 36 | // rijndael-api-fst.h 37 | // 38 | // Optimised ANSI C code 39 | // 40 | // authors: v1.0: Antoon Bosselaers 41 | // v2.0: Vincent Rijmen, K.U.Leuven 42 | // v2.3: Paulo Barreto 43 | // v2.4: Vincent Rijmen, K.U.Leuven 44 | // 45 | // This code is placed in the public domain. 46 | // 47 | 48 | // 49 | // This implementation works on 128 , 192 , 256 bit keys 50 | // and on 128 bit blocks 51 | // 52 | 53 | // 54 | // Example of usage: 55 | // 56 | // // Input data 57 | // unsigned char key[32]; // The key 58 | // initializeYour256BitKey(); // Obviously initialized with sth 59 | // const unsigned char * plainText = getYourPlainText(); // Your plain text 60 | // int plainTextLen = strlen(plainText); // Plain text length 61 | // 62 | // // Encrypting 63 | // Rijndael rin; 64 | // unsigned char output[plainTextLen + 16]; 65 | // 66 | // rin.init(Rijndael::CBC,Rijndael::Encrypt,key,Rijndael::Key32Bytes); 67 | // // It is a good idea to check the error code 68 | // int len = rin.padEncrypt(plainText,len,output); 69 | // if(len >= 0)useYourEncryptedText(); 70 | // else encryptError(len); 71 | // 72 | // // Decrypting: we can reuse the same object 73 | // unsigned char output2[len]; 74 | // rin.init(Rijndael::CBC,Rijndael::Decrypt,key,Rijndael::Key32Bytes)); 75 | // len = rin.padDecrypt(output,len,output2); 76 | // if(len >= 0)useYourDecryptedText(); 77 | // else decryptError(len); 78 | // 79 | */ 80 | 81 | #define _MAX_KEY_COLUMNS (256/32) 82 | #define _MAX_ROUNDS 14 83 | #define MAX_IV_SIZE 16 84 | 85 | /* We assume that unsigned int is 32 bits long.... */ 86 | typedef unsigned char UINT8; 87 | typedef unsigned int UINT32; 88 | typedef unsigned short UINT16; 89 | 90 | /* Error codes */ 91 | #define RIJNDAEL_SUCCESS 0 92 | #define RIJNDAEL_UNSUPPORTED_MODE -1 93 | #define RIJNDAEL_UNSUPPORTED_DIRECTION -2 94 | #define RIJNDAEL_UNSUPPORTED_KEY_LENGTH -3 95 | #define RIJNDAEL_BAD_KEY -4 96 | #define RIJNDAEL_NOT_INITIALIZED -5 97 | #define RIJNDAEL_BAD_DIRECTION -6 98 | #define RIJNDAEL_CORRUPTED_DATA -7 99 | 100 | #define RIJNDAEL_Direction_Encrypt 0 101 | #define RIJNDAEL_Direction_Decrypt 1 102 | 103 | #define RIJNDAEL_Direction_Mode_ECB 0 104 | #define RIJNDAEL_Direction_Mode_CBC 1 105 | #define RIJNDAEL_Direction_Mode_CFB1 2 106 | 107 | #define RIJNDAEL_Direction_KeyLength_Key16Bytes 0 108 | #define RIJNDAEL_Direction_KeyLength_Key24Bytes 1 109 | #define RIJNDAEL_Direction_KeyLength_Key32Bytes 2 110 | 111 | #define RIJNDAEL_State_Valid 0 112 | #define RIJNDAEL_State_Invalid 1 113 | 114 | /* 115 | /// Class implementing the Rijndael cipher. (For internal use only) 116 | */ 117 | 118 | typedef struct _Rijndael 119 | { 120 | int m_state; 121 | int m_mode; 122 | int m_direction; 123 | UINT8 m_initVector[MAX_IV_SIZE]; 124 | UINT32 m_uRounds; 125 | UINT8 m_expandedKey[_MAX_ROUNDS+1][4][4]; 126 | } Rijndael; 127 | 128 | void RijndaelCreate(Rijndael* rijndael); 129 | 130 | /* 131 | ////////////////////////////////////////////////////////////////////////////////////////// 132 | // API 133 | ////////////////////////////////////////////////////////////////////////////////////////// 134 | 135 | // init(): Initializes the crypt session 136 | // Returns RIJNDAEL_SUCCESS or an error code 137 | // mode : Rijndael::ECB, Rijndael::CBC or Rijndael::CFB1 138 | // You have to use the same mode for encrypting and decrypting 139 | // dir : Rijndael::Encrypt or Rijndael::Decrypt 140 | // A cipher instance works only in one direction 141 | // (Well , it could be easily modified to work in both 142 | // directions with a single init() call, but it looks 143 | // useless to me...anyway , it is a matter of generating 144 | // two expanded keys) 145 | // key : array of unsigned octets , it can be 16 , 24 or 32 bytes long 146 | // this CAN be binary data (it is not expected to be null terminated) 147 | // keyLen : Rijndael::Key16Bytes , Rijndael::Key24Bytes or Rijndael::Key32Bytes 148 | // initVector: initialization vector, you will usually use 0 here 149 | */ 150 | int RijndaelInit(Rijndael* rijndael, int mode, int dir, UINT8* key, int keyLen, UINT8* initVector); 151 | 152 | /* 153 | // Encrypts the input array (can be binary data) 154 | // The input array length must be a multiple of 16 bytes, the remaining part 155 | // is DISCARDED. 156 | // so it actually encrypts inputLen / 128 blocks of input and puts it in outBuffer 157 | // Input len is in BITS! 158 | // outBuffer must be at least inputLen / 8 bytes long. 159 | // Returns the encrypted buffer length in BITS or an error code < 0 in case of error 160 | */ 161 | int RijndaelBlockEncrypt(Rijndael* rijndael, UINT8 *input, int inputLen, UINT8 *outBuffer); 162 | 163 | /* 164 | // Encrypts the input array (can be binary data) 165 | // The input array can be any length , it is automatically padded on a 16 byte boundary. 166 | // Input len is in BYTES! 167 | // outBuffer must be at least (inputLen + 16) bytes long 168 | // Returns the encrypted buffer length in BYTES or an error code < 0 in case of error 169 | */ 170 | int RijndaelPadEncrypt(Rijndael* rijndael, UINT8 *input, int inputOctets, UINT8 *outBuffer); 171 | 172 | /* 173 | // Decrypts the input vector 174 | // Input len is in BITS! 175 | // outBuffer must be at least inputLen / 8 bytes long 176 | // Returns the decrypted buffer length in BITS and an error code < 0 in case of error 177 | */ 178 | int RijndaelBlockDecrypt(Rijndael* rijndael, UINT8 *input, int inputLen, UINT8 *outBuffer); 179 | 180 | /* 181 | // Decrypts the input vector 182 | // Input len is in BYTES! 183 | // outBuffer must be at least inputLen bytes long 184 | // Returns the decrypted buffer length in BYTES and an error code < 0 in case of error 185 | */ 186 | int RijndaelPadDecrypt(Rijndael* rijndael, UINT8 *input, int inputOctets, UINT8 *outBuffer); 187 | 188 | void RijndaelInvalidate(Rijndael* rijndael); 189 | void RijndaelKeySched(Rijndael* rijndael, UINT8 key[_MAX_KEY_COLUMNS][4]); 190 | void RijndaelKeyEncToDec(Rijndael* rijndael); 191 | void RijndaelEncrypt(Rijndael* rijndael, UINT8 a[16], UINT8 b[16]); 192 | void RijndaelDecrypt(Rijndael* rijndael, UINT8 a[16], UINT8 b[16]); 193 | 194 | #endif /* _RIJNDAEL_H_ */ 195 | -------------------------------------------------------------------------------- /wxsqlite3/sha1.h: -------------------------------------------------------------------------------- 1 | /* public api for steve reid's public domain SHA-1 implementation */ 2 | /* this file is in the public domain */ 3 | 4 | #ifndef SHA1_H_ 5 | #define SHA1_H_ (1) 6 | 7 | /** SHA-1 Context */ 8 | typedef struct { 9 | uint32_t h[5]; 10 | /**< Context state */ 11 | uint32_t count[2]; 12 | /**< Counter */ 13 | uint8_t buffer[64]; /**< SHA-1 buffer */ 14 | } sha1_ctx; 15 | 16 | #define SHA1_BLOCK_SIZE 64 17 | /** SHA-1 Digest size in bytes */ 18 | #define SHA1_DIGEST_SIZE 20 19 | 20 | void sha1_init(sha1_ctx *context); 21 | 22 | void sha1_update(sha1_ctx *context, const void *p, size_t len); 23 | 24 | void sha1_final(sha1_ctx *context, uint8_t digest[SHA1_DIGEST_SIZE]); 25 | 26 | void sha1_transform(sha1_ctx *context, const uint8_t buffer[64]); 27 | 28 | #endif /* SHA1_H_ */ 29 | -------------------------------------------------------------------------------- /wxsqlite3/sha2.h: -------------------------------------------------------------------------------- 1 | /* 2 | * FIPS 180-2 SHA-224/256/384/512 implementation 3 | * Last update: 02/02/2007 4 | * Issue date: 04/30/2005 5 | * 6 | * Copyright (C) 2005, 2007 Olivier Gay 7 | * All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 1. Redistributions of source code must retain the above copyright 13 | * notice, this list of conditions and the following disclaimer. 14 | * 2. Redistributions in binary form must reproduce the above copyright 15 | * notice, this list of conditions and the following disclaimer in the 16 | * documentation and/or other materials provided with the distribution. 17 | * 3. Neither the name of the project nor the names of its contributors 18 | * may be used to endorse or promote products derived from this software 19 | * without specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 22 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 | * SUCH DAMAGE. 32 | */ 33 | 34 | #ifndef SHA2_H 35 | #define SHA2_H 36 | 37 | #define SHA224_DIGEST_SIZE ( 224 / 8) 38 | #define SHA256_DIGEST_SIZE ( 256 / 8) 39 | #define SHA384_DIGEST_SIZE ( 384 / 8) 40 | #define SHA512_DIGEST_SIZE ( 512 / 8) 41 | 42 | #define SHA256_BLOCK_SIZE ( 512 / 8) 43 | #define SHA512_BLOCK_SIZE (1024 / 8) 44 | #define SHA384_BLOCK_SIZE SHA512_BLOCK_SIZE 45 | #define SHA224_BLOCK_SIZE SHA256_BLOCK_SIZE 46 | 47 | #ifndef SHA2_TYPES 48 | #define SHA2_TYPES 49 | typedef unsigned char uint8; 50 | typedef unsigned int uint32; 51 | 52 | typedef sqlite3_uint64 uint64; 53 | 54 | #if defined(_MSC_VER) || defined(__BORLANDC__) 55 | #define li_64(h) 0x##h##ui64 56 | #else 57 | #define li_64(h) 0x##h##ull 58 | #endif 59 | 60 | #if 0 /* Start of original int64 defines */ 61 | 62 | #if defined(_MSC_VER) 63 | #if _MSC_VER >= 1310 64 | typedef unsigned long long uint64; 65 | #define li_64(h) 0x##h##ull 66 | #else 67 | typedef unsigned __int64 uint64; 68 | #define li_64(h) 0x##h##ui64 69 | #endif 70 | #elif defined(__BORLANDC__) && !defined(__MSDOS__) 71 | #define li_64(h) 0x##h##ull 72 | typedef __int64 uint64; 73 | #elif defined(__sun) 74 | #if defined(ULONG_MAX) && ULONG_MAX == 0xfffffffful 75 | #define li_64(h) 0x##h##ull 76 | typedef unsigned long long uint64; 77 | #elif defined(ULONG_LONG_MAX) && ULONG_LONG_MAX == 0xfffffffffffffffful 78 | #define li_64(h) 0x##h##ul 79 | typedef unsigned long uint64; 80 | #endif 81 | #elif defined(__MVS__) 82 | #define li_64(h) 0x##h##ull 83 | typedef unsigned int long long uint64; 84 | #elif defined(ULLONG_MAX) && ULLONG_MAX > 4294967295 85 | #if ULLONG_MAX == 18446744073709551615ull 86 | #define li_64(h) 0x##h##ull 87 | typedef unsigned long long uint64; 88 | #endif 89 | #elif defined(ULONG_LONG_MAX) && ULONG_LONG_MAX > 4294967295 90 | #if ULONG_LONG_MAX == 18446744073709551615 91 | #define li_64(h) 0x##h##ull 92 | typedef unsigned long long uint64; 93 | #endif 94 | #elif defined(ULONG_MAX) && ULONG_MAX > 4294967295 95 | #if ULONG_MAX == 18446744073709551615 96 | #define li_64(h) 0x##h##ul 97 | typedef unsigned long uint64; 98 | #endif 99 | #elif defined(UINT_MAX) && UINT_MAX > 4294967295 100 | #if UINT_MAX == 18446744073709551615 101 | #define li_64(h) 0x##h##u 102 | typedef unsigned int uint64; 103 | #endif 104 | #endif 105 | #endif 106 | 107 | #endif /* End of original int64 defines */ 108 | 109 | #ifdef __cplusplus 110 | extern "C" { 111 | #endif 112 | 113 | typedef struct { 114 | unsigned int tot_len; 115 | unsigned int len; 116 | unsigned char block[2 * SHA256_BLOCK_SIZE]; 117 | uint32 h[8]; 118 | } sha256_ctx; 119 | 120 | typedef struct { 121 | unsigned int tot_len; 122 | unsigned int len; 123 | unsigned char block[2 * SHA512_BLOCK_SIZE]; 124 | uint64 h[8]; 125 | } sha512_ctx; 126 | 127 | typedef sha512_ctx sha384_ctx; 128 | typedef sha256_ctx sha224_ctx; 129 | 130 | void sha224_init(sha224_ctx *ctx); 131 | void sha224_update(sha224_ctx *ctx, const unsigned char *message, 132 | unsigned int len); 133 | void sha224_final(sha224_ctx *ctx, unsigned char *digest); 134 | void sha224(const unsigned char *message, unsigned int len, 135 | unsigned char *digest); 136 | 137 | void sha256_init(sha256_ctx * ctx); 138 | void sha256_update(sha256_ctx *ctx, const unsigned char *message, 139 | unsigned int len); 140 | void sha256_final(sha256_ctx *ctx, unsigned char *digest); 141 | void sha256_transform(sha256_ctx *ctx, const unsigned char *message); 142 | void sha256(const unsigned char *message, unsigned int len, 143 | unsigned char *digest); 144 | 145 | void sha384_init(sha384_ctx *ctx); 146 | void sha384_update(sha384_ctx *ctx, const unsigned char *message, 147 | unsigned int len); 148 | void sha384_final(sha384_ctx *ctx, unsigned char *digest); 149 | void sha384(const unsigned char *message, unsigned int len, 150 | unsigned char *digest); 151 | 152 | void sha512_init(sha512_ctx *ctx); 153 | void sha512_update(sha512_ctx *ctx, const unsigned char *message, 154 | unsigned int len); 155 | void sha512_final(sha512_ctx *ctx, unsigned char *digest); 156 | void sha512_transform(sha512_ctx *ctx, const unsigned char *message); 157 | void sha512(const unsigned char *message, unsigned int len, 158 | unsigned char *digest); 159 | 160 | #ifdef __cplusplus 161 | } 162 | #endif 163 | 164 | #endif /* !SHA2_H */ 165 | 166 | -------------------------------------------------------------------------------- /wxsqlite3/sqlite370.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jathon-yang/go-wxsqlite3/9cecf6d69b21b08c250ed990606253af3bfc2672/wxsqlite3/sqlite370.ico -------------------------------------------------------------------------------- /wxsqlite3/sqlite3mc.def: -------------------------------------------------------------------------------- 1 | EXPORTS 2 | sqlite3_activate_see 3 | sqlite3_aggregate_context 4 | sqlite3_aggregate_count 5 | sqlite3_auto_extension 6 | sqlite3_autovacuum_pages 7 | sqlite3_backup_finish 8 | sqlite3_backup_init 9 | sqlite3_backup_pagecount 10 | sqlite3_backup_remaining 11 | sqlite3_backup_step 12 | sqlite3_bind_blob 13 | sqlite3_bind_blob64 14 | sqlite3_bind_double 15 | sqlite3_bind_int 16 | sqlite3_bind_int64 17 | sqlite3_bind_null 18 | sqlite3_bind_parameter_count 19 | sqlite3_bind_parameter_index 20 | sqlite3_bind_parameter_name 21 | sqlite3_bind_pointer 22 | sqlite3_bind_text 23 | sqlite3_bind_text16 24 | sqlite3_bind_text64 25 | sqlite3_bind_value 26 | sqlite3_bind_zeroblob 27 | sqlite3_bind_zeroblob64 28 | sqlite3_blob_bytes 29 | sqlite3_blob_close 30 | sqlite3_blob_open 31 | sqlite3_blob_read 32 | sqlite3_blob_reopen 33 | sqlite3_blob_write 34 | sqlite3_busy_handler 35 | sqlite3_busy_timeout 36 | sqlite3_cancel_auto_extension 37 | sqlite3_changes 38 | sqlite3_clear_bindings 39 | sqlite3_close 40 | sqlite3_close_v2 41 | sqlite3_collation_needed 42 | sqlite3_collation_needed16 43 | sqlite3_column_blob 44 | sqlite3_column_bytes 45 | sqlite3_column_bytes16 46 | sqlite3_column_count 47 | sqlite3_column_database_name 48 | sqlite3_column_database_name16 49 | sqlite3_column_decltype 50 | sqlite3_column_decltype16 51 | sqlite3_column_double 52 | sqlite3_column_int 53 | sqlite3_column_int64 54 | sqlite3_column_name 55 | sqlite3_column_name16 56 | sqlite3_column_origin_name 57 | sqlite3_column_origin_name16 58 | sqlite3_column_table_name 59 | sqlite3_column_table_name16 60 | sqlite3_column_text 61 | sqlite3_column_text16 62 | sqlite3_column_type 63 | sqlite3_column_value 64 | sqlite3_commit_hook 65 | sqlite3_compileoption_get 66 | sqlite3_compileoption_used 67 | sqlite3_complete 68 | sqlite3_complete16 69 | sqlite3_config 70 | sqlite3_context_db_handle 71 | sqlite3_create_collation 72 | sqlite3_create_collation16 73 | sqlite3_create_collation_v2 74 | sqlite3_create_filename 75 | sqlite3_create_function 76 | sqlite3_create_function16 77 | sqlite3_create_function_v2 78 | sqlite3_create_module 79 | sqlite3_create_module_v2 80 | sqlite3_create_window_function 81 | sqlite3_data_count 82 | sqlite3_database_file_object 83 | sqlite3_db_cacheflush 84 | sqlite3_db_config 85 | sqlite3_db_filename 86 | sqlite3_db_handle 87 | sqlite3_db_mutex 88 | sqlite3_db_readonly 89 | sqlite3_db_release_memory 90 | sqlite3_db_status 91 | sqlite3_declare_vtab 92 | sqlite3_deserialize 93 | sqlite3_drop_modules 94 | sqlite3_enable_load_extension 95 | sqlite3_enable_shared_cache 96 | sqlite3_errcode 97 | sqlite3_errmsg 98 | sqlite3_errmsg16 99 | sqlite3_error_offset 100 | sqlite3_errstr 101 | sqlite3_exec 102 | sqlite3_expanded_sql 103 | sqlite3_expired 104 | sqlite3_extended_errcode 105 | sqlite3_extended_result_codes 106 | sqlite3_file_control 107 | sqlite3_filename_database 108 | sqlite3_filename_journal 109 | sqlite3_filename_wal 110 | sqlite3_finalize 111 | sqlite3_free 112 | sqlite3_free_filename 113 | sqlite3_free_table 114 | sqlite3_get_autocommit 115 | sqlite3_get_auxdata 116 | sqlite3_get_table 117 | sqlite3_global_recover 118 | sqlite3_hard_heap_limit64 119 | sqlite3_initialize 120 | sqlite3_interrupt 121 | sqlite3_key 122 | sqlite3_key_v2 123 | sqlite3_keyword_check 124 | sqlite3_keyword_count 125 | sqlite3_keyword_name 126 | sqlite3_last_insert_rowid 127 | sqlite3_libversion 128 | sqlite3_libversion_number 129 | sqlite3_limit 130 | sqlite3_load_extension 131 | sqlite3_log 132 | sqlite3_malloc 133 | sqlite3_malloc64 134 | sqlite3_memory_alarm 135 | sqlite3_memory_highwater 136 | sqlite3_memory_used 137 | sqlite3_mprintf 138 | sqlite3_msize 139 | sqlite3_mutex_alloc 140 | sqlite3_mutex_enter 141 | sqlite3_mutex_free 142 | sqlite3_mutex_leave 143 | sqlite3_mutex_try 144 | sqlite3_next_stmt 145 | sqlite3_open 146 | sqlite3_open16 147 | sqlite3_open_v2 148 | sqlite3_os_end 149 | sqlite3_os_init 150 | sqlite3_overload_function 151 | sqlite3_prepare 152 | sqlite3_prepare16 153 | sqlite3_prepare16_v2 154 | sqlite3_prepare16_v3 155 | sqlite3_prepare_v2 156 | sqlite3_prepare_v3 157 | sqlite3_profile 158 | sqlite3_progress_handler 159 | sqlite3_randomness 160 | sqlite3_realloc 161 | sqlite3_realloc64 162 | sqlite3_rekey 163 | sqlite3_rekey_v2 164 | sqlite3_release_memory 165 | sqlite3_reset 166 | sqlite3_reset_auto_extension 167 | sqlite3_result_blob 168 | sqlite3_result_blob64 169 | sqlite3_result_double 170 | sqlite3_result_error 171 | sqlite3_result_error16 172 | sqlite3_result_error_code 173 | sqlite3_result_error_nomem 174 | sqlite3_result_error_toobig 175 | sqlite3_result_int 176 | sqlite3_result_int64 177 | sqlite3_result_null 178 | sqlite3_result_pointer 179 | sqlite3_result_subtype 180 | sqlite3_result_text 181 | sqlite3_result_text16 182 | sqlite3_result_text16be 183 | sqlite3_result_text16le 184 | sqlite3_result_text64 185 | sqlite3_result_value 186 | sqlite3_result_zeroblob 187 | sqlite3_result_zeroblob64 188 | sqlite3_rollback_hook 189 | sqlite3_rtree_geometry_callback 190 | sqlite3_rtree_query_callback 191 | sqlite3_serialize 192 | sqlite3_set_authorizer 193 | sqlite3_set_auxdata 194 | sqlite3_set_last_insert_rowid 195 | sqlite3_shutdown 196 | sqlite3_sleep 197 | sqlite3_snprintf 198 | sqlite3_soft_heap_limit 199 | sqlite3_soft_heap_limit64 200 | sqlite3_sourceid 201 | sqlite3_sql 202 | sqlite3_status 203 | sqlite3_status64 204 | sqlite3_step 205 | sqlite3_stmt_busy 206 | sqlite3_stmt_isexplain 207 | sqlite3_stmt_readonly 208 | sqlite3_stmt_status 209 | sqlite3_str_append 210 | sqlite3_str_appendall 211 | sqlite3_str_appendchar 212 | sqlite3_str_appendf 213 | sqlite3_str_errcode 214 | sqlite3_str_finish 215 | sqlite3_str_length 216 | sqlite3_str_new 217 | sqlite3_str_reset 218 | sqlite3_str_value 219 | sqlite3_str_vappendf 220 | sqlite3_strglob 221 | sqlite3_stricmp 222 | sqlite3_strlike 223 | sqlite3_strnicmp 224 | sqlite3_system_errno 225 | sqlite3_table_column_metadata 226 | sqlite3_test_control 227 | sqlite3_thread_cleanup 228 | sqlite3_threadsafe 229 | sqlite3_total_changes 230 | sqlite3_total_changes64 231 | sqlite3_trace 232 | sqlite3_trace_v2 233 | sqlite3_transfer_bindings 234 | sqlite3_txn_state 235 | sqlite3_update_hook 236 | sqlite3_uri_boolean 237 | sqlite3_uri_int64 238 | sqlite3_uri_key 239 | sqlite3_uri_parameter 240 | sqlite3_user_data 241 | sqlite3_user_add 242 | sqlite3_user_authenticate 243 | sqlite3_user_change 244 | sqlite3_user_delete 245 | sqlite3_value_blob 246 | sqlite3_value_bytes 247 | sqlite3_value_bytes16 248 | sqlite3_value_double 249 | sqlite3_value_dup 250 | sqlite3_value_free 251 | sqlite3_value_frombind 252 | sqlite3_value_int 253 | sqlite3_value_int64 254 | sqlite3_value_nochange 255 | sqlite3_value_numeric_type 256 | sqlite3_value_pointer 257 | sqlite3_value_subtype 258 | sqlite3_value_text 259 | sqlite3_value_text16 260 | sqlite3_value_text16be 261 | sqlite3_value_text16le 262 | sqlite3_value_type 263 | sqlite3_vfs_find 264 | sqlite3_vfs_register 265 | sqlite3_vfs_unregister 266 | sqlite3_vmprintf 267 | sqlite3_vsnprintf 268 | sqlite3_vtab_collation 269 | sqlite3_vtab_config 270 | sqlite3_vtab_distinct 271 | sqlite3_vtab_in 272 | sqlite3_vtab_in_first 273 | sqlite3_vtab_in_next 274 | sqlite3_vtab_nochange 275 | sqlite3_vtab_on_conflict 276 | sqlite3_vtab_rhs_value 277 | sqlite3_wal_autocheckpoint 278 | sqlite3_wal_checkpoint 279 | sqlite3_wal_checkpoint_v2 280 | sqlite3_wal_hook 281 | sqlite3_win32_is_nt 282 | sqlite3_win32_mbcs_to_utf8 283 | sqlite3_win32_mbcs_to_utf8_v2 284 | sqlite3_win32_set_directory 285 | sqlite3_win32_set_directory16 286 | sqlite3_win32_set_directory8 287 | sqlite3_win32_sleep 288 | sqlite3_win32_unicode_to_utf8 289 | sqlite3_win32_utf8_to_mbcs 290 | sqlite3_win32_utf8_to_mbcs_v2 291 | sqlite3_win32_utf8_to_unicode 292 | sqlite3_win32_write_debug 293 | sqlite3mc_codec_data 294 | sqlite3mc_config 295 | sqlite3mc_config_cipher 296 | sqlite3mc_version 297 | sqlite3mc_vfs_create 298 | sqlite3mc_vfs_destroy 299 | sqlite3mc_vfs_shutdown 300 | -------------------------------------------------------------------------------- /wxsqlite3/sqlite3mc.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Name: sqlite3mc.h 3 | ** Purpose: Header file for SQLite3 Multiple Ciphers support 4 | ** Author: Ulrich Telle 5 | ** Created: 2020-03-01 6 | ** Copyright: (c) 2019-2021 Ulrich Telle 7 | ** License: MIT 8 | */ 9 | 10 | #ifndef SQLITE3MC_H_ 11 | #define SQLITE3MC_H_ 12 | 13 | /* 14 | ** Define SQLite3 Multiple Ciphers version information 15 | */ 16 | #include "sqlite3mc_version.h" 17 | 18 | /* 19 | ** Define SQLite3 API 20 | */ 21 | #include "sqlite3.h" 22 | 23 | #ifdef SQLITE_USER_AUTHENTICATION 24 | #include "sqlite3userauth.h" 25 | #endif 26 | 27 | /* 28 | ** Symbols for ciphers 29 | */ 30 | #define CODEC_TYPE_UNKNOWN 0 31 | #define CODEC_TYPE_AES128 1 32 | #define CODEC_TYPE_AES256 2 33 | #define CODEC_TYPE_CHACHA20 3 34 | #define CODEC_TYPE_SQLCIPHER 4 35 | #define CODEC_TYPE_RC4 5 36 | #define CODEC_TYPE_MAX 5 37 | 38 | /* 39 | ** Definition of API functions 40 | */ 41 | 42 | /* 43 | ** Define Windows specific SQLite API functions (not defined in sqlite3.h) 44 | */ 45 | #if SQLITE_OS_WIN == 1 46 | 47 | #ifdef __cplusplus 48 | extern "C" { 49 | #endif 50 | 51 | SQLITE_API int sqlite3_win32_set_directory(unsigned long type, void* zValue); 52 | 53 | #ifdef __cplusplus 54 | } 55 | #endif 56 | 57 | #endif 58 | 59 | #ifdef __cplusplus 60 | extern "C" { 61 | #endif 62 | 63 | /* 64 | ** Specify the key for an encrypted database. 65 | ** This routine should be called right after sqlite3_open(). 66 | ** 67 | ** Arguments: 68 | ** db - Database to be encrypted 69 | ** zDbName - Name of the database (e.g. "main") 70 | ** pKey - Passphrase 71 | ** nKey - Length of passphrase 72 | */ 73 | SQLITE_API int sqlite3_key(sqlite3* db, const void* pKey, int nKey); 74 | SQLITE_API int sqlite3_key_v2(sqlite3* db, const char* zDbName, const void* pKey, int nKey); 75 | 76 | /* 77 | ** Change the key on an open database. 78 | ** If the current database is not encrypted, this routine will encrypt 79 | ** it. If pNew==0 or nNew==0, the database is decrypted. 80 | ** 81 | ** Arguments: 82 | ** db - Database to be encrypted 83 | ** zDbName - Name of the database (e.g. "main") 84 | ** pKey - Passphrase 85 | ** nKey - Length of passphrase 86 | */ 87 | SQLITE_API int sqlite3_rekey(sqlite3* db, const void* pKey, int nKey); 88 | SQLITE_API int sqlite3_rekey_v2(sqlite3* db, const char* zDbName, const void* pKey, int nKey); 89 | 90 | /* 91 | ** Specify the activation key for a SEE database. 92 | ** Unless activated, none of the SEE routines will work. 93 | ** 94 | ** Arguments: 95 | ** zPassPhrase - Activation phrase 96 | ** 97 | ** Note: Provided only for API compatibility with SEE. 98 | ** Encryption support of SQLite3 Multi Cipher is always enabled. 99 | */ 100 | SQLITE_API void sqlite3_activate_see(const char* zPassPhrase); 101 | 102 | /* 103 | ** Define functions for the configuration of the wxSQLite3 encryption extension 104 | */ 105 | SQLITE_API int sqlite3mc_config(sqlite3* db, const char* paramName, int newValue); 106 | SQLITE_API int sqlite3mc_config_cipher(sqlite3* db, const char* cipherName, const char* paramName, int newValue); 107 | SQLITE_API unsigned char* sqlite3mc_codec_data(sqlite3* db, const char* zDbName, const char* paramName); 108 | SQLITE_API const char* sqlite3mc_version(); 109 | 110 | #ifdef SQLITE3MC_WXSQLITE3_COMPATIBLE 111 | SQLITE_API int wxsqlite3_config(sqlite3* db, const char* paramName, int newValue); 112 | SQLITE_API int wxsqlite3_config_cipher(sqlite3* db, const char* cipherName, const char* paramName, int newValue); 113 | SQLITE_API unsigned char* wxsqlite3_codec_data(sqlite3* db, const char* zDbName, const char* paramName); 114 | #endif 115 | 116 | #ifdef __cplusplus 117 | } 118 | #endif 119 | 120 | /* 121 | ** Define public SQLite3 Multiple Ciphers VFS interface 122 | */ 123 | #include "sqlite3mc_vfs.h" 124 | 125 | #endif 126 | -------------------------------------------------------------------------------- /wxsqlite3/sqlite3mc.rc: -------------------------------------------------------------------------------- 1 | #ifdef APSTUDIO_INVOKED 2 | #error This file is not editable by Microsoft Visual C++ 3 | #endif /* APSTUDIO_INVOKED */ 4 | 5 | /* 6 | ** SQLITE3MC_STRINGIZE works as the preprocessor # operator but also works with macros 7 | */ 8 | #define SQLITE3MC_STRINGIZE_HELPER(x) #x 9 | #define SQLITE3MC_STRINGIZE(x) SQLITE3MC_STRINGIZE_HELPER(x) 10 | 11 | /* 12 | ** Version 13 | */ 14 | #include "sqlite3mc_version.h" 15 | #include 16 | 17 | #define SQLITE3MC_MAKE_VERSION_DOT_STRING(x, y, z, w) \ 18 | SQLITE3MC_STRINGIZE(x) "." SQLITE3MC_STRINGIZE(y) "." SQLITE3MC_STRINGIZE(z) "." SQLITE3MC_STRINGIZE(w) 19 | 20 | #define SQLITE3MC_FILE_VERSION_NUM_DOT_STRING \ 21 | SQLITE3MC_MAKE_VERSION_DOT_STRING(SQLITE3MC_VERSION_MAJOR, SQLITE3MC_VERSION_MINOR, SQLITE3MC_VERSION_RELEASE, SQLITE3MC_VERSION_SUBRELEASE) 22 | #define SQLITE3MC_PROD_VERSION_NUM_DOT_STRING \ 23 | SQLITE3MC_MAKE_VERSION_DOT_STRING(SQLITE3MC_VERSION_MAJOR, SQLITE3MC_VERSION_MINOR, SQLITE3MC_VERSION_RELEASE, SQLITE3MC_VERSION_SUBRELEASE) 24 | 25 | // 0x0409 is US English, 0x04b0 is Unicode and 0x0000 is 7 bit ASCII. see 26 | // http://msdn.microsoft.com/en-us/library/aa381049(VS.85).aspx for the full 27 | // list of languages and charsets 28 | #define LANG 0x0409 29 | #ifdef _UNICODE 30 | #define CHARSET 0x4b0 31 | #define LANG_WITH_CHARSET "040904b0" 32 | #else 33 | #define CHARSET 0 34 | #define LANG_WITH_CHARSET "04090000" 35 | #endif 36 | 37 | VS_VERSION_INFO VERSIONINFO 38 | FILEVERSION SQLITE3MC_VERSION_MAJOR,SQLITE3MC_VERSION_MINOR,SQLITE3MC_VERSION_RELEASE,SQLITE3MC_VERSION_SUBRELEASE 39 | PRODUCTVERSION SQLITE3MC_VERSION_MAJOR,SQLITE3MC_VERSION_MINOR,SQLITE3MC_VERSION_RELEASE,SQLITE3MC_VERSION_SUBRELEASE 40 | FILEFLAGSMASK 0x3fL 41 | #ifdef _DEBUG 42 | FILEFLAGS 0x1L 43 | #else 44 | FILEFLAGS 0x0L 45 | #endif 46 | FILEOS VOS_NT_WINDOWS32 47 | FILETYPE VFT_DLL 48 | FILESUBTYPE 0x0L 49 | BEGIN 50 | BLOCK "StringFileInfo" 51 | BEGIN 52 | BLOCK LANG_WITH_CHARSET 53 | BEGIN 54 | VALUE "CompanyName", "SQLite3 Multiple Ciphers Development Team" 55 | VALUE "FileDescription", "SQLite3 Multiple Ciphers Database Library" 56 | VALUE "FileVersion", SQLITE3MC_FILE_VERSION_NUM_DOT_STRING 57 | VALUE "InternalName", "sqlite3mc.dll" 58 | VALUE "LegalCopyright", "Copyright (C) 2019-2020, Ulrich Telle" 59 | VALUE "OriginalFilename", "sqlite3mc.dll" 60 | VALUE "ProductName", "SQLite3 Multiple Ciphers" 61 | VALUE "ProductVersion", SQLITE3MC_PROD_VERSION_NUM_DOT_STRING 62 | END 63 | END 64 | BLOCK "VarFileInfo" 65 | BEGIN 66 | VALUE "Translation", LANG, CHARSET 67 | END 68 | END 69 | -------------------------------------------------------------------------------- /wxsqlite3/sqlite3mc_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Name: sqlite3mc_config.h 3 | ** Purpose: Header file for SQLite3 Multiple Ciphers compile-time configuration 4 | ** Author: Ulrich Telle 5 | ** Created: 2021-09-27 6 | ** Copyright: (c) 2019-2021 Ulrich Telle 7 | ** License: MIT 8 | */ 9 | 10 | #ifndef SQLITE3MC_CONFIG_H_ 11 | #define SQLITE3MC_CONFIG_H_ 12 | 13 | /* 14 | ** Definitions of supported ciphers 15 | */ 16 | 17 | /* 18 | ** Compatibility with wxSQLite3 19 | */ 20 | #ifdef WXSQLITE3_HAVE_CIPHER_AES_128_CBC 21 | #define HAVE_CIPHER_AES_128_CBC WXSQLITE3_HAVE_CIPHER_AES_128_CBC 22 | #endif 23 | 24 | #ifdef WXSQLITE3_HAVE_CIPHER_AES_256_CBC 25 | #define HAVE_CIPHER_AES_256_CBC WXSQLITE3_HAVE_CIPHER_AES_256_CBC 26 | #endif 27 | 28 | #ifdef WXSQLITE3_HAVE_CIPHER_CHACHA20 29 | #define HAVE_CIPHER_CHACHA20 WXSQLITE3_HAVE_CIPHER_CHACHA20 30 | #endif 31 | 32 | #ifdef WXSQLITE3_HAVE_CIPHER_SQLCIPHER 33 | #define HAVE_CIPHER_SQLCIPHER WXSQLITE3_HAVE_CIPHER_SQLCIPHER 34 | #endif 35 | 36 | #ifdef WXSQLITE3_HAVE_CIPHER_RC4 37 | #define HAVE_CIPHER_RC4 WXSQLITE3_HAVE_CIPHER_RC4 38 | #endif 39 | 40 | /* 41 | ** Actual definitions of supported ciphers 42 | */ 43 | #ifndef HAVE_CIPHER_AES_128_CBC 44 | #define HAVE_CIPHER_AES_128_CBC 1 45 | #endif 46 | 47 | #ifndef HAVE_CIPHER_AES_256_CBC 48 | #define HAVE_CIPHER_AES_256_CBC 1 49 | #endif 50 | 51 | #ifndef HAVE_CIPHER_CHACHA20 52 | #define HAVE_CIPHER_CHACHA20 1 53 | #endif 54 | 55 | #ifndef HAVE_CIPHER_SQLCIPHER 56 | #define HAVE_CIPHER_SQLCIPHER 1 57 | #endif 58 | 59 | #ifndef HAVE_CIPHER_RC4 60 | #define HAVE_CIPHER_RC4 1 61 | #endif 62 | 63 | /* 64 | ** Check that at least one cipher is be supported 65 | */ 66 | #if HAVE_CIPHER_AES_128_CBC == 0 && \ 67 | HAVE_CIPHER_AES_256_CBC == 0 && \ 68 | HAVE_CIPHER_CHACHA20 == 0 && \ 69 | HAVE_CIPHER_SQLCIPHER == 0 && \ 70 | HAVE_CIPHER_RC4 == 0 71 | #error Enable at least one cipher scheme! 72 | #endif 73 | 74 | /* 75 | ** Compile-time configuration 76 | */ 77 | 78 | /* 79 | ** Selection of default cipher scheme 80 | ** 81 | ** A specific default cipher scheme can be selected by defining 82 | ** the symbol CODEC_TYPE using one of the cipher scheme values 83 | ** CODEC_TYPE_AES128, CODEC_TYPE_AES256, CODEC_TYPE_CHACHA20, 84 | ** CODEC_TYPE_SQLCIPHER, or CODEC_TYPE_RC4. 85 | ** 86 | ** If the symbol CODEC_TYPE is not defined, CODEC_TYPE_CHACHA20 87 | ** is selected as the default cipher scheme. 88 | */ 89 | #if 0 90 | #define CODEC_TYPE CODEC_TYPE_CHACHA20 91 | #endif 92 | 93 | /* 94 | ** Selection of legacy mode 95 | ** 96 | ** A) CODEC_TYPE_AES128 and CODEC_TYPE_AES256 97 | ** Defining the symbol WXSQLITE3_USE_OLD_ENCRYPTION_SCHEME 98 | ** selects the legacy mode for both cipher schemes. 99 | ** 100 | ** B) CODEC_TYPE_CHACHA20 101 | ** Defining the symbol SQLITE3MC_USE_SQLEET_LEGACY 102 | ** selects the legacy mode. 103 | ** 104 | ** C) CODEC_TYPE_SQLCIPHER 105 | ** Defining the symbol SQLITE3MC_USE_SQLEET_LEGACY 106 | ** selects the legacy mode. 107 | ** 108 | ** D) CODEC_TYPE_RC4 109 | ** This cipher scheme is available in legacy mode only. 110 | */ 111 | 112 | #if 0 113 | #define WXSQLITE3_USE_OLD_ENCRYPTION_SCHEME 114 | #endif 115 | 116 | #if 0 117 | #define SQLITE3MC_USE_SQLEET_LEGACY 118 | #endif 119 | 120 | #if 0 121 | #define SQLITE3MC_USE_SQLCIPHER_LEGACY 122 | #endif 123 | 124 | /* 125 | ** Selection of default version for SQLCipher scheme 126 | ** 127 | ** A specific default version can be selected by defining 128 | ** the symbol SQLCIPHER_VERSION_DEFAULT using one of the 129 | ** supported version values (SQLCIPHER_VERSION_1, 130 | ** SQLCIPHER_VERSION_2, SQLCIPHER_VERSION_3, SQLCIPHER_VERSION_4). 131 | ** 132 | ** If the symbol SQLCIPHER_VERSION_DEFAULT is not defined, 133 | ** version 4 (SQLCIPHER_VERSION_4) is selected as the default value. 134 | */ 135 | 136 | #if 0 137 | #define SQLCIPHER_VERSION_DEFAULT SQLCIPHER_VERSION_4 138 | #endif 139 | 140 | #endif 141 | -------------------------------------------------------------------------------- /wxsqlite3/sqlite3mc_shell.rc: -------------------------------------------------------------------------------- 1 | #ifdef APSTUDIO_INVOKED 2 | #error This file is not editable by Microsoft Visual C++ 3 | #endif /* APSTUDIO_INVOKED */ 4 | 5 | /* 6 | ** SQLITE3MC_STRINGIZE works as the preprocessor # operator but also works with macros 7 | */ 8 | #define SQLITE3MC_STRINGIZE_HELPER(x) #x 9 | #define SQLITE3MC_STRINGIZE(x) SQLITE3MC_STRINGIZE_HELPER(x) 10 | 11 | /* 12 | ** Version 13 | */ 14 | ID_SQLITE3 ICON "sqlite370.ico" 15 | 16 | #include "sqlite3mc_version.h" 17 | #include 18 | 19 | #define SQLITE3MC_MAKE_VERSION_DOT_STRING(x, y, z, w) \ 20 | SQLITE3MC_STRINGIZE(x) "." SQLITE3MC_STRINGIZE(y) "." SQLITE3MC_STRINGIZE(z) "." SQLITE3MC_STRINGIZE(w) 21 | 22 | #define SQLITE3MC_FILE_VERSION_NUM_DOT_STRING \ 23 | SQLITE3MC_MAKE_VERSION_DOT_STRING(SQLITE3MC_VERSION_MAJOR, SQLITE3MC_VERSION_MINOR, SQLITE3MC_VERSION_RELEASE, SQLITE3MC_VERSION_SUBRELEASE) 24 | #define SQLITE3MC_PROD_VERSION_NUM_DOT_STRING \ 25 | SQLITE3MC_MAKE_VERSION_DOT_STRING(SQLITE3MC_VERSION_MAJOR, SQLITE3MC_VERSION_MINOR, SQLITE3MC_VERSION_RELEASE, SQLITE3MC_VERSION_SUBRELEASE) 26 | 27 | // 0x0409 is US English, 0x04b0 is Unicode and 0x0000 is 7 bit ASCII. see 28 | // http://msdn.microsoft.com/en-us/library/aa381049(VS.85).aspx for the full 29 | // list of languages and charsets 30 | #define LANG 0x0409 31 | #ifdef _UNICODE 32 | #define CHARSET 0x4b0 33 | #define LANG_WITH_CHARSET "040904b0" 34 | #else 35 | #define CHARSET 0 36 | #define LANG_WITH_CHARSET "04090000" 37 | #endif 38 | 39 | VS_VERSION_INFO VERSIONINFO 40 | FILEVERSION SQLITE3MC_VERSION_MAJOR,SQLITE3MC_VERSION_MINOR,SQLITE3MC_VERSION_RELEASE,SQLITE3MC_VERSION_SUBRELEASE 41 | PRODUCTVERSION SQLITE3MC_VERSION_MAJOR,SQLITE3MC_VERSION_MINOR,SQLITE3MC_VERSION_RELEASE,SQLITE3MC_VERSION_SUBRELEASE 42 | FILEFLAGSMASK 0x3fL 43 | #ifdef _DEBUG 44 | FILEFLAGS 0x1L 45 | #else 46 | FILEFLAGS 0x0L 47 | #endif 48 | FILEOS VOS_NT_WINDOWS32 49 | FILETYPE VFT_APP 50 | FILESUBTYPE 0x0L 51 | BEGIN 52 | BLOCK "StringFileInfo" 53 | BEGIN 54 | BLOCK LANG_WITH_CHARSET 55 | BEGIN 56 | VALUE "CompanyName", "SQLite3 Multiple Ciphers Development Team" 57 | VALUE "FileDescription", "SQLite3 Multiple Ciphers Database Shell" 58 | VALUE "FileVersion", SQLITE3MC_FILE_VERSION_NUM_DOT_STRING 59 | VALUE "InternalName", "sqlite3mc_shell.exe" 60 | VALUE "LegalCopyright", "Copyright (C) 2019-2020, Ulrich Telle" 61 | VALUE "OriginalFilename", "sqlite3mc_shell.exe" 62 | VALUE "ProductName", "SQLite3 Multiple Ciphers" 63 | VALUE "ProductVersion", SQLITE3MC_PROD_VERSION_NUM_DOT_STRING 64 | END 65 | END 66 | BLOCK "VarFileInfo" 67 | BEGIN 68 | VALUE "Translation", LANG, CHARSET 69 | END 70 | END 71 | -------------------------------------------------------------------------------- /wxsqlite3/sqlite3mc_version.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Name: sqlite3mc_version.h 3 | ** Purpose: SQLite3 Multiple Ciphers version numbers 4 | ** Author: Ulrich Telle 5 | ** Created: 2020-08-05 6 | ** Copyright: (c) 2020-2021 Ulrich Telle 7 | ** License: MIT 8 | */ 9 | 10 | /// \file sqlite3mc_version.h Version information for the SQLite3 Multiple Ciphers library 11 | 12 | #ifndef SQLITE3MC_VERSION_H_ 13 | #define SQLITE3MC_VERSION_H_ 14 | 15 | #define SQLITE3MC_VERSION_MAJOR 1 16 | #define SQLITE3MC_VERSION_MINOR 3 17 | #define SQLITE3MC_VERSION_RELEASE 8 18 | #define SQLITE3MC_VERSION_SUBRELEASE 0 19 | #define SQLITE3MC_VERSION_STRING "SQLite3 Multiple Ciphers 1.3.8" 20 | 21 | #endif /* SQLITE3MC_VERSION_H_ */ 22 | -------------------------------------------------------------------------------- /wxsqlite3/sqlite3mc_vfs.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Name: sqlite3mc_vfs.h 3 | ** Purpose: Header file for VFS of SQLite3 Multiple Ciphers support 4 | ** Author: Ulrich Telle 5 | ** Created: 2020-03-01 6 | ** Copyright: (c) 2020 Ulrich Telle 7 | ** License: MIT 8 | */ 9 | 10 | #ifndef SQLITE3MC_VFS_H_ 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | SQLITE_API int sqlite3mc_vfs_create(const char* zVfsReal, int makeDefault); 17 | SQLITE_API void sqlite3mc_vfs_destroy(const char* zName); 18 | SQLITE_API void sqlite3mc_vfs_shutdown(); 19 | 20 | #ifdef __cplusplus 21 | } 22 | #endif 23 | 24 | #endif /* SQLITE3MC_VFS_H_ */ 25 | -------------------------------------------------------------------------------- /wxsqlite3/sqlite3userauth.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** 2014-09-08 3 | ** 4 | ** The author disclaims copyright to this source code. In place of 5 | ** a legal notice, here is a blessing: 6 | ** 7 | ** May you do good and not evil. 8 | ** May you find forgiveness for yourself and forgive others. 9 | ** May you share freely, never taking more than you give. 10 | ** 11 | ************************************************************************* 12 | ** 13 | ** This file contains the application interface definitions for the 14 | ** user-authentication extension feature. 15 | ** 16 | ** To compile with the user-authentication feature, append this file to 17 | ** end of an SQLite amalgamation header file ("sqlite3.h"), then add 18 | ** the SQLITE_USER_AUTHENTICATION compile-time option. See the 19 | ** user-auth.txt file in the same source directory as this file for 20 | ** additional information. 21 | */ 22 | #ifdef SQLITE_USER_AUTHENTICATION 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | /* 29 | ** If a database contains the SQLITE_USER table, then the 30 | ** sqlite3_user_authenticate() interface must be invoked with an 31 | ** appropriate username and password prior to enable read and write 32 | ** access to the database. 33 | ** 34 | ** Return SQLITE_OK on success or SQLITE_ERROR if the username/password 35 | ** combination is incorrect or unknown. 36 | ** 37 | ** If the SQLITE_USER table is not present in the database file, then 38 | ** this interface is a harmless no-op returnning SQLITE_OK. 39 | */ 40 | int sqlite3_user_authenticate( 41 | sqlite3 *db, /* The database connection */ 42 | const char *zUsername, /* Username */ 43 | const char *aPW, /* Password or credentials */ 44 | int nPW /* Number of bytes in aPW[] */ 45 | ); 46 | 47 | /* 48 | ** The sqlite3_user_add() interface can be used (by an admin user only) 49 | ** to create a new user. When called on a no-authentication-required 50 | ** database, this routine converts the database into an authentication- 51 | ** required database, automatically makes the added user an 52 | ** administrator, and logs in the current connection as that user. 53 | ** The sqlite3_user_add() interface only works for the "main" database, not 54 | ** for any ATTACH-ed databases. Any call to sqlite3_user_add() by a 55 | ** non-admin user results in an error. 56 | */ 57 | int sqlite3_user_add( 58 | sqlite3 *db, /* Database connection */ 59 | const char *zUsername, /* Username to be added */ 60 | const char *aPW, /* Password or credentials */ 61 | int nPW, /* Number of bytes in aPW[] */ 62 | int isAdmin /* True to give new user admin privilege */ 63 | ); 64 | 65 | /* 66 | ** The sqlite3_user_change() interface can be used to change a users 67 | ** login credentials or admin privilege. Any user can change their own 68 | ** login credentials. Only an admin user can change another users login 69 | ** credentials or admin privilege setting. No user may change their own 70 | ** admin privilege setting. 71 | */ 72 | int sqlite3_user_change( 73 | sqlite3 *db, /* Database connection */ 74 | const char *zUsername, /* Username to change */ 75 | const char *aPW, /* New password or credentials */ 76 | int nPW, /* Number of bytes in aPW[] */ 77 | int isAdmin /* Modified admin privilege for the user */ 78 | ); 79 | 80 | /* 81 | ** The sqlite3_user_delete() interface can be used (by an admin user only) 82 | ** to delete a user. The currently logged-in user cannot be deleted, 83 | ** which guarantees that there is always an admin user and hence that 84 | ** the database cannot be converted into a no-authentication-required 85 | ** database. 86 | */ 87 | int sqlite3_user_delete( 88 | sqlite3 *db, /* Database connection */ 89 | const char *zUsername /* Username to remove */ 90 | ); 91 | 92 | #ifdef __cplusplus 93 | } /* end of the 'extern "C"' block */ 94 | #endif 95 | 96 | #endif /* SQLITE_USER_AUTHENTICATION */ 97 | -------------------------------------------------------------------------------- /wxsqlite3/test_windirent.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** 2015 November 30 3 | ** 4 | ** The author disclaims copyright to this source code. In place of 5 | ** a legal notice, here is a blessing: 6 | ** 7 | ** May you do good and not evil. 8 | ** May you find forgiveness for yourself and forgive others. 9 | ** May you share freely, never taking more than you give. 10 | ** 11 | ************************************************************************* 12 | ** This file contains code to implement most of the opendir() family of 13 | ** POSIX functions on Win32 using the MSVCRT. 14 | */ 15 | 16 | #if defined(_WIN32) && defined(_MSC_VER) 17 | #include "test_windirent.h" 18 | 19 | /* 20 | ** Implementation of the POSIX getenv() function using the Win32 API. 21 | ** This function is not thread-safe. 22 | */ 23 | const char *windirent_getenv( 24 | const char *name 25 | ){ 26 | static char value[32768]; /* Maximum length, per MSDN */ 27 | DWORD dwSize = sizeof(value) / sizeof(char); /* Size in chars */ 28 | DWORD dwRet; /* Value returned by GetEnvironmentVariableA() */ 29 | 30 | memset(value, 0, sizeof(value)); 31 | dwRet = GetEnvironmentVariableA(name, value, dwSize); 32 | if( dwRet==0 || dwRet>dwSize ){ 33 | /* 34 | ** The function call to GetEnvironmentVariableA() failed -OR- 35 | ** the buffer is not large enough. Either way, return NULL. 36 | */ 37 | return 0; 38 | }else{ 39 | /* 40 | ** The function call to GetEnvironmentVariableA() succeeded 41 | ** -AND- the buffer contains the entire value. 42 | */ 43 | return value; 44 | } 45 | } 46 | 47 | /* 48 | ** Implementation of the POSIX opendir() function using the MSVCRT. 49 | */ 50 | LPDIR opendir( 51 | const char *dirname 52 | ){ 53 | struct _finddata_t data; 54 | LPDIR dirp = (LPDIR)sqlite3_malloc(sizeof(DIR)); 55 | SIZE_T namesize = sizeof(data.name) / sizeof(data.name[0]); 56 | 57 | if( dirp==NULL ) return NULL; 58 | memset(dirp, 0, sizeof(DIR)); 59 | 60 | /* TODO: Remove this if Unix-style root paths are not used. */ 61 | if( sqlite3_stricmp(dirname, "/")==0 ){ 62 | dirname = windirent_getenv("SystemDrive"); 63 | } 64 | 65 | memset(&data, 0, sizeof(struct _finddata_t)); 66 | _snprintf(data.name, namesize, "%s\\*", dirname); 67 | dirp->d_handle = _findfirst(data.name, &data); 68 | 69 | if( dirp->d_handle==BAD_INTPTR_T ){ 70 | closedir(dirp); 71 | return NULL; 72 | } 73 | 74 | /* TODO: Remove this block to allow hidden and/or system files. */ 75 | if( is_filtered(data) ){ 76 | next: 77 | 78 | memset(&data, 0, sizeof(struct _finddata_t)); 79 | if( _findnext(dirp->d_handle, &data)==-1 ){ 80 | closedir(dirp); 81 | return NULL; 82 | } 83 | 84 | /* TODO: Remove this block to allow hidden and/or system files. */ 85 | if( is_filtered(data) ) goto next; 86 | } 87 | 88 | dirp->d_first.d_attributes = data.attrib; 89 | strncpy(dirp->d_first.d_name, data.name, NAME_MAX); 90 | dirp->d_first.d_name[NAME_MAX] = '\0'; 91 | 92 | return dirp; 93 | } 94 | 95 | /* 96 | ** Implementation of the POSIX readdir() function using the MSVCRT. 97 | */ 98 | LPDIRENT readdir( 99 | LPDIR dirp 100 | ){ 101 | struct _finddata_t data; 102 | 103 | if( dirp==NULL ) return NULL; 104 | 105 | if( dirp->d_first.d_ino==0 ){ 106 | dirp->d_first.d_ino++; 107 | dirp->d_next.d_ino++; 108 | 109 | return &dirp->d_first; 110 | } 111 | 112 | next: 113 | 114 | memset(&data, 0, sizeof(struct _finddata_t)); 115 | if( _findnext(dirp->d_handle, &data)==-1 ) return NULL; 116 | 117 | /* TODO: Remove this block to allow hidden and/or system files. */ 118 | if( is_filtered(data) ) goto next; 119 | 120 | dirp->d_next.d_ino++; 121 | dirp->d_next.d_attributes = data.attrib; 122 | strncpy(dirp->d_next.d_name, data.name, NAME_MAX); 123 | dirp->d_next.d_name[NAME_MAX] = '\0'; 124 | 125 | return &dirp->d_next; 126 | } 127 | 128 | /* 129 | ** Implementation of the POSIX readdir_r() function using the MSVCRT. 130 | */ 131 | INT readdir_r( 132 | LPDIR dirp, 133 | LPDIRENT entry, 134 | LPDIRENT *result 135 | ){ 136 | struct _finddata_t data; 137 | 138 | if( dirp==NULL ) return EBADF; 139 | 140 | if( dirp->d_first.d_ino==0 ){ 141 | dirp->d_first.d_ino++; 142 | dirp->d_next.d_ino++; 143 | 144 | entry->d_ino = dirp->d_first.d_ino; 145 | entry->d_attributes = dirp->d_first.d_attributes; 146 | strncpy(entry->d_name, dirp->d_first.d_name, NAME_MAX); 147 | entry->d_name[NAME_MAX] = '\0'; 148 | 149 | *result = entry; 150 | return 0; 151 | } 152 | 153 | next: 154 | 155 | memset(&data, 0, sizeof(struct _finddata_t)); 156 | if( _findnext(dirp->d_handle, &data)==-1 ){ 157 | *result = NULL; 158 | return ENOENT; 159 | } 160 | 161 | /* TODO: Remove this block to allow hidden and/or system files. */ 162 | if( is_filtered(data) ) goto next; 163 | 164 | entry->d_ino = (ino_t)-1; /* not available */ 165 | entry->d_attributes = data.attrib; 166 | strncpy(entry->d_name, data.name, NAME_MAX); 167 | entry->d_name[NAME_MAX] = '\0'; 168 | 169 | *result = entry; 170 | return 0; 171 | } 172 | 173 | /* 174 | ** Implementation of the POSIX closedir() function using the MSVCRT. 175 | */ 176 | INT closedir( 177 | LPDIR dirp 178 | ){ 179 | INT result = 0; 180 | 181 | if( dirp==NULL ) return EINVAL; 182 | 183 | if( dirp->d_handle!=NULL_INTPTR_T && dirp->d_handle!=BAD_INTPTR_T ){ 184 | result = _findclose(dirp->d_handle); 185 | } 186 | 187 | sqlite3_free(dirp); 188 | return result; 189 | } 190 | 191 | #endif /* defined(WIN32) && defined(_MSC_VER) */ 192 | -------------------------------------------------------------------------------- /wxsqlite3/test_windirent.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** 2015 November 30 3 | ** 4 | ** The author disclaims copyright to this source code. In place of 5 | ** a legal notice, here is a blessing: 6 | ** 7 | ** May you do good and not evil. 8 | ** May you find forgiveness for yourself and forgive others. 9 | ** May you share freely, never taking more than you give. 10 | ** 11 | ************************************************************************* 12 | ** This file contains declarations for most of the opendir() family of 13 | ** POSIX functions on Win32 using the MSVCRT. 14 | */ 15 | 16 | #if defined(_WIN32) && defined(_MSC_VER) && !defined(SQLITE_WINDIRENT_H) 17 | #define SQLITE_WINDIRENT_H 18 | 19 | /* 20 | ** We need several data types from the Windows SDK header. 21 | */ 22 | 23 | #ifndef WIN32_LEAN_AND_MEAN 24 | #define WIN32_LEAN_AND_MEAN 25 | #endif 26 | 27 | #include "windows.h" 28 | 29 | /* 30 | ** We need several support functions from the SQLite core. 31 | */ 32 | 33 | #include "sqlite3.h" 34 | 35 | /* 36 | ** We need several things from the ANSI and MSVCRT headers. 37 | */ 38 | 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | 47 | /* 48 | ** We may need several defines that should have been in "sys/stat.h". 49 | */ 50 | 51 | #ifndef S_ISREG 52 | #define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) 53 | #endif 54 | 55 | #ifndef S_ISDIR 56 | #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) 57 | #endif 58 | 59 | #ifndef S_ISLNK 60 | #define S_ISLNK(mode) (0) 61 | #endif 62 | 63 | /* 64 | ** We may need to provide the "mode_t" type. 65 | */ 66 | 67 | #ifndef MODE_T_DEFINED 68 | #define MODE_T_DEFINED 69 | typedef unsigned short mode_t; 70 | #endif 71 | 72 | /* 73 | ** We may need to provide the "ino_t" type. 74 | */ 75 | 76 | #ifndef INO_T_DEFINED 77 | #define INO_T_DEFINED 78 | typedef unsigned short ino_t; 79 | #endif 80 | 81 | /* 82 | ** We need to define "NAME_MAX" if it was not present in "limits.h". 83 | */ 84 | 85 | #ifndef NAME_MAX 86 | # ifdef FILENAME_MAX 87 | # define NAME_MAX (FILENAME_MAX) 88 | # else 89 | # define NAME_MAX (260) 90 | # endif 91 | #endif 92 | 93 | /* 94 | ** We need to define "NULL_INTPTR_T" and "BAD_INTPTR_T". 95 | */ 96 | 97 | #ifndef NULL_INTPTR_T 98 | # define NULL_INTPTR_T ((intptr_t)(0)) 99 | #endif 100 | 101 | #ifndef BAD_INTPTR_T 102 | # define BAD_INTPTR_T ((intptr_t)(-1)) 103 | #endif 104 | 105 | /* 106 | ** We need to provide the necessary structures and related types. 107 | */ 108 | 109 | #ifndef DIRENT_DEFINED 110 | #define DIRENT_DEFINED 111 | typedef struct DIRENT DIRENT; 112 | typedef DIRENT *LPDIRENT; 113 | struct DIRENT { 114 | ino_t d_ino; /* Sequence number, do not use. */ 115 | unsigned d_attributes; /* Win32 file attributes. */ 116 | char d_name[NAME_MAX + 1]; /* Name within the directory. */ 117 | }; 118 | #endif 119 | 120 | #ifndef DIR_DEFINED 121 | #define DIR_DEFINED 122 | typedef struct DIR DIR; 123 | typedef DIR *LPDIR; 124 | struct DIR { 125 | intptr_t d_handle; /* Value returned by "_findfirst". */ 126 | DIRENT d_first; /* DIRENT constructed based on "_findfirst". */ 127 | DIRENT d_next; /* DIRENT constructed based on "_findnext". */ 128 | }; 129 | #endif 130 | 131 | /* 132 | ** Provide a macro, for use by the implementation, to determine if a 133 | ** particular directory entry should be skipped over when searching for 134 | ** the next directory entry that should be returned by the readdir() or 135 | ** readdir_r() functions. 136 | */ 137 | 138 | #ifndef is_filtered 139 | # define is_filtered(a) ((((a).attrib)&_A_HIDDEN) || (((a).attrib)&_A_SYSTEM)) 140 | #endif 141 | 142 | /* 143 | ** Provide the function prototype for the POSIX compatiable getenv() 144 | ** function. This function is not thread-safe. 145 | */ 146 | 147 | extern const char *windirent_getenv(const char *name); 148 | 149 | /* 150 | ** Finally, we can provide the function prototypes for the opendir(), 151 | ** readdir(), readdir_r(), and closedir() POSIX functions. 152 | */ 153 | 154 | extern LPDIR opendir(const char *dirname); 155 | extern LPDIRENT readdir(LPDIR dirp); 156 | extern INT readdir_r(LPDIR dirp, LPDIRENT entry, LPDIRENT *result); 157 | extern INT closedir(LPDIR dirp); 158 | 159 | #endif /* defined(WIN32) && defined(_MSC_VER) */ 160 | -------------------------------------------------------------------------------- /wxsqlite3/uuid.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** 2019-10-23 3 | ** 4 | ** The author disclaims copyright to this source code. In place of 5 | ** a legal notice, here is a blessing: 6 | ** 7 | ** May you do good and not evil. 8 | ** May you find forgiveness for yourself and forgive others. 9 | ** May you share freely, never taking more than you give. 10 | ** 11 | ****************************************************************************** 12 | ** 13 | ** This SQLite extension implements functions that handling RFC-4122 UUIDs 14 | ** Three SQL functions are implemented: 15 | ** 16 | ** uuid() - generate a version 4 UUID as a string 17 | ** uuid_str(X) - convert a UUID X into a well-formed UUID string 18 | ** uuid_blob(X) - convert a UUID X into a 16-byte blob 19 | ** 20 | ** The output from uuid() and uuid_str(X) are always well-formed RFC-4122 21 | ** UUID strings in this format: 22 | ** 23 | ** xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx 24 | ** 25 | ** All of the 'x', 'M', and 'N' values are lower-case hexadecimal digits. 26 | ** The M digit indicates the "version". For uuid()-generated UUIDs, the 27 | ** version is always "4" (a random UUID). The upper three bits of N digit 28 | ** are the "variant". This library only supports variant 1 (indicated 29 | ** by values of N between '8' and 'b') as those are overwhelming the most 30 | ** common. Other variants are for legacy compatibility only. 31 | ** 32 | ** The output of uuid_blob(X) is always a 16-byte blob. The UUID input 33 | ** string is converted in network byte order (big-endian) in accordance 34 | ** with RFC-4122 specifications for variant-1 UUIDs. Note that network 35 | ** byte order is *always* used, even if the input self-identifies as a 36 | ** variant-2 UUID. 37 | ** 38 | ** The input X to the uuid_str() and uuid_blob() functions can be either 39 | ** a string or a BLOB. If it is a BLOB it must be exactly 16 bytes in 40 | ** length or else a NULL is returned. If the input is a string it must 41 | ** consist of 32 hexadecimal digits, upper or lower case, optionally 42 | ** surrounded by {...} and with optional "-" characters interposed in the 43 | ** middle. The flexibility of input is inspired by the PostgreSQL 44 | ** implementation of UUID functions that accept in all of the following 45 | ** formats: 46 | ** 47 | ** A0EEBC99-9C0B-4EF8-BB6D-6BB9BD380A11 48 | ** {a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11} 49 | ** a0eebc999c0b4ef8bb6d6bb9bd380a11 50 | ** a0ee-bc99-9c0b-4ef8-bb6d-6bb9-bd38-0a11 51 | ** {a0eebc99-9c0b4ef8-bb6d6bb9-bd380a11} 52 | ** 53 | ** If any of the above inputs are passed into uuid_str(), the output will 54 | ** always be in the canonical RFC-4122 format: 55 | ** 56 | ** a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11 57 | ** 58 | ** If the X input string has too few or too many digits or contains 59 | ** stray characters other than {, }, or -, then NULL is returned. 60 | */ 61 | #include "sqlite3ext.h" 62 | SQLITE_EXTENSION_INIT1 63 | #include 64 | #include 65 | #include 66 | 67 | #if !defined(SQLITE_ASCII) && !defined(SQLITE_EBCDIC) 68 | # define SQLITE_ASCII 1 69 | #endif 70 | 71 | /* 72 | ** Translate a single byte of Hex into an integer. 73 | ** This routine only works if h really is a valid hexadecimal 74 | ** character: 0..9a..fA..F 75 | */ 76 | static unsigned char sqlite3UuidHexToInt(int h){ 77 | assert( (h>='0' && h<='9') || (h>='a' && h<='f') || (h>='A' && h<='F') ); 78 | #ifdef SQLITE_ASCII 79 | h += 9*(1&(h>>6)); 80 | #endif 81 | #ifdef SQLITE_EBCDIC 82 | h += 9*(1&~(h>>4)); 83 | #endif 84 | return (unsigned char)(h & 0xf); 85 | } 86 | 87 | /* 88 | ** Convert a 16-byte BLOB into a well-formed RFC-4122 UUID. The output 89 | ** buffer zStr should be at least 37 bytes in length. The output will 90 | ** be zero-terminated. 91 | */ 92 | static void sqlite3UuidBlobToStr( 93 | const unsigned char *aBlob, /* Input blob */ 94 | unsigned char *zStr /* Write the answer here */ 95 | ){ 96 | static const char zDigits[] = "0123456789abcdef"; 97 | int i, k; 98 | unsigned char x; 99 | k = 0; 100 | for(i=0, k=0x550; i<16; i++, k=k>>1){ 101 | if( k&1 ){ 102 | zStr[0] = '-'; 103 | zStr++; 104 | } 105 | x = aBlob[i]; 106 | zStr[0] = zDigits[x>>4]; 107 | zStr[1] = zDigits[x&0xf]; 108 | zStr += 2; 109 | } 110 | *zStr = 0; 111 | } 112 | 113 | /* 114 | ** Attempt to parse a zero-terminated input string zStr into a binary 115 | ** UUID. Return 0 on success, or non-zero if the input string is not 116 | ** parsable. 117 | */ 118 | static int sqlite3UuidStrToBlob( 119 | const unsigned char *zStr, /* Input string */ 120 | unsigned char *aBlob /* Write results here */ 121 | ){ 122 | int i; 123 | if( zStr[0]=='{' ) zStr++; 124 | for(i=0; i<16; i++){ 125 | if( zStr[0]=='-' ) zStr++; 126 | if( isxdigit(zStr[0]) && isxdigit(zStr[1]) ){ 127 | aBlob[i] = (sqlite3UuidHexToInt(zStr[0])<<4) 128 | + sqlite3UuidHexToInt(zStr[1]); 129 | zStr += 2; 130 | }else{ 131 | return 1; 132 | } 133 | } 134 | if( zStr[0]=='}' ) zStr++; 135 | return zStr[0]!=0; 136 | } 137 | 138 | /* 139 | ** Render sqlite3_value pIn as a 16-byte UUID blob. Return a pointer 140 | ** to the blob, or NULL if the input is not well-formed. 141 | */ 142 | static const unsigned char *sqlite3UuidInputToBlob( 143 | sqlite3_value *pIn, /* Input text */ 144 | unsigned char *pBuf /* output buffer */ 145 | ){ 146 | switch( sqlite3_value_type(pIn) ){ 147 | case SQLITE_TEXT: { 148 | const unsigned char *z = sqlite3_value_text(pIn); 149 | if( sqlite3UuidStrToBlob(z, pBuf) ) return 0; 150 | return pBuf; 151 | } 152 | case SQLITE_BLOB: { 153 | int n = sqlite3_value_bytes(pIn); 154 | return n==16 ? sqlite3_value_blob(pIn) : 0; 155 | } 156 | default: { 157 | return 0; 158 | } 159 | } 160 | } 161 | 162 | /* Implementation of uuid() */ 163 | static void sqlite3UuidFunc( 164 | sqlite3_context *context, 165 | int argc, 166 | sqlite3_value **argv 167 | ){ 168 | unsigned char aBlob[16]; 169 | unsigned char zStr[37]; 170 | (void)argc; 171 | (void)argv; 172 | sqlite3_randomness(16, aBlob); 173 | aBlob[6] = (aBlob[6]&0x0f) + 0x40; 174 | aBlob[8] = (aBlob[8]&0x3f) + 0x80; 175 | sqlite3UuidBlobToStr(aBlob, zStr); 176 | sqlite3_result_text(context, (char*)zStr, 36, SQLITE_TRANSIENT); 177 | } 178 | 179 | /* Implementation of uuid_str() */ 180 | static void sqlite3UuidStrFunc( 181 | sqlite3_context *context, 182 | int argc, 183 | sqlite3_value **argv 184 | ){ 185 | unsigned char aBlob[16]; 186 | unsigned char zStr[37]; 187 | const unsigned char *pBlob; 188 | (void)argc; 189 | pBlob = sqlite3UuidInputToBlob(argv[0], aBlob); 190 | if( pBlob==0 ) return; 191 | sqlite3UuidBlobToStr(pBlob, zStr); 192 | sqlite3_result_text(context, (char*)zStr, 36, SQLITE_TRANSIENT); 193 | } 194 | 195 | /* Implementation of uuid_blob() */ 196 | static void sqlite3UuidBlobFunc( 197 | sqlite3_context *context, 198 | int argc, 199 | sqlite3_value **argv 200 | ){ 201 | unsigned char aBlob[16]; 202 | const unsigned char *pBlob; 203 | (void)argc; 204 | pBlob = sqlite3UuidInputToBlob(argv[0], aBlob); 205 | if( pBlob==0 ) return; 206 | sqlite3_result_blob(context, pBlob, 16, SQLITE_TRANSIENT); 207 | } 208 | 209 | #ifdef _WIN32 210 | __declspec(dllexport) 211 | #endif 212 | int sqlite3_uuid_init( 213 | sqlite3 *db, 214 | char **pzErrMsg, 215 | const sqlite3_api_routines *pApi 216 | ){ 217 | int rc = SQLITE_OK; 218 | SQLITE_EXTENSION_INIT2(pApi); 219 | (void)pzErrMsg; /* Unused parameter */ 220 | rc = sqlite3_create_function(db, "uuid", 0, SQLITE_UTF8|SQLITE_INNOCUOUS, 0, 221 | sqlite3UuidFunc, 0, 0); 222 | if( rc==SQLITE_OK ){ 223 | rc = sqlite3_create_function(db, "uuid_str", 1, 224 | SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC, 225 | 0, sqlite3UuidStrFunc, 0, 0); 226 | } 227 | if( rc==SQLITE_OK ){ 228 | rc = sqlite3_create_function(db, "uuid_blob", 1, 229 | SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC, 230 | 0, sqlite3UuidBlobFunc, 0, 0); 231 | } 232 | return rc; 233 | } 234 | -------------------------------------------------------------------------------- /wxsqlite3_cgo.go: -------------------------------------------------------------------------------- 1 | package sqlite3 2 | 3 | /* 4 | #cgo linux,amd64 CFLAGS: -msse4.1 5 | #cgo !arm64 CFLAGS: -maes 6 | #cgo CFLAGS: -DUSE_LIBSQLITE3 -DCODEC_TYPE=CODEC_TYPE_AES128 -DSQLITE_HAS_CODEC=1 7 | */ 8 | import "C" --------------------------------------------------------------------------------