boxafe 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE.txt +1 -1
- data/README.md +118 -1
- data/VERSION +1 -1
- data/bin/boxafe +2 -1
- data/lib/boxafe/box.rb +104 -0
- data/lib/boxafe/cli.rb +93 -0
- data/lib/boxafe/config.rb +50 -0
- data/lib/boxafe/encfs.rb +31 -0
- data/lib/boxafe/program.rb +96 -0
- data/lib/boxafe/scheduler/cron.rb +25 -0
- data/lib/boxafe/scheduler/launchd.rb +39 -0
- data/lib/boxafe/scheduler.rb +18 -0
- data/lib/boxafe.rb +13 -1
- metadata +59 -120
- checksums.yaml +0 -7
- data/.rspec +0 -2
- data/.ruby-gemset +0 -1
- data/.ruby-version +0 -1
- data/.screenrc +0 -8
- data/.travis.yml +0 -5
- data/Gemfile +0 -21
- data/Gemfile.lock +0 -59
- data/Rakefile +0 -51
- data/lib/program.rb +0 -18
- data/spec/helper.rb +0 -16
- data/spec/version_spec.rb +0 -9
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,123 @@
|
|
1
1
|
# boxafe
|
2
2
|
|
3
|
-
|
3
|
+
[](http://badge.fury.io/rb/boxafe)
|
4
|
+
[](https://gemnasium.com/AlphaHydrae/boxafe)
|
5
|
+
[](http://travis-ci.org/AlphaHydrae/boxafe)
|
6
|
+
|
7
|
+
Boxafe mounts EncFS filesystems or "boxes" that you define in a configuration file with a friendly DSL.
|
8
|
+
It can also mount them on startup.
|
9
|
+
|
10
|
+
**Note: Currently supports OS X. Partial Linux support.**
|
11
|
+
|
12
|
+
## Installation
|
13
|
+
|
14
|
+
gem install boxafe
|
15
|
+
|
16
|
+
## Configuration
|
17
|
+
|
18
|
+
Location: `~/.boxafe.rb`
|
19
|
+
|
20
|
+
```rb
|
21
|
+
# mount a box (this will prompt for your password)
|
22
|
+
box do
|
23
|
+
name 'A box'
|
24
|
+
root '/secure/abox'
|
25
|
+
mount '/Volumes/abox'
|
26
|
+
end
|
27
|
+
# this command is run:
|
28
|
+
# encfs "/secure/abox" "/Volumes/abox" -- -ovolname="A box"
|
29
|
+
|
30
|
+
# get the password from the OS X keychain
|
31
|
+
box do
|
32
|
+
name 'Keychain box'
|
33
|
+
root '/secure/keychain-box'
|
34
|
+
mount '/Volumes/keychain-box'
|
35
|
+
keychain 'keychain-box-password'
|
36
|
+
end
|
37
|
+
# adds an extpass to the command:
|
38
|
+
# --extpass="security 2>&1 >/dev/null find-generic-password -gl 'keychain-box-password'
|
39
|
+
|
40
|
+
# specify a custom path to the encfs XML configuration file
|
41
|
+
box do
|
42
|
+
name 'Custom box'
|
43
|
+
root '/secure/custom-box'
|
44
|
+
mount '/Volumes/custom-box'
|
45
|
+
encfs_config '/secure/.custom-box.encfs6.xml'
|
46
|
+
end
|
47
|
+
# adds an environment variable:
|
48
|
+
# ENCFS6_CONFIG="/secure/.custom-box.encfs6.xml"
|
49
|
+
|
50
|
+
# use a volume name different than the name
|
51
|
+
box do
|
52
|
+
name 'Volume box'
|
53
|
+
root '/secure/volume-box'
|
54
|
+
mount '/Volumes/volume-box'
|
55
|
+
volume 'Secure Volume'
|
56
|
+
end
|
57
|
+
# changes the ovolname option
|
58
|
+
|
59
|
+
# use a hash configuration
|
60
|
+
config = {
|
61
|
+
name: 'Hash box',
|
62
|
+
root: '/secure/hash-box',
|
63
|
+
mount: '/Volumes/hash-box'
|
64
|
+
}
|
65
|
+
box config
|
66
|
+
|
67
|
+
# load configuration from environment variables
|
68
|
+
box env(:box_name, :box_root, :box_mount) # Reads $BOX_NAME, $BOX_ROOT, $BOX_MOUNT
|
69
|
+
|
70
|
+
# customize path to binaries
|
71
|
+
encfs '/opt/local/bin/encfs'
|
72
|
+
umount '/usr/local/bin/umount'
|
73
|
+
```
|
74
|
+
|
75
|
+
## Usage
|
76
|
+
|
77
|
+
```bash
|
78
|
+
# mount/unmount all defined boxes
|
79
|
+
boxafe mount
|
80
|
+
boxafe unmount
|
81
|
+
|
82
|
+
# mount/unmount one box
|
83
|
+
boxafe mount 'A box'
|
84
|
+
boxafe unmount 'A box'
|
85
|
+
|
86
|
+
# check what boxes are mounted
|
87
|
+
boxafe status
|
88
|
+
|
89
|
+
# mount all boxes on startup (currently only on OS X)
|
90
|
+
boxafe start
|
91
|
+
|
92
|
+
# stop boxes from mounting on startup
|
93
|
+
boxafe stop
|
94
|
+
```
|
95
|
+
|
96
|
+
## Compatibility
|
97
|
+
|
98
|
+
Boxafe is currently geared towards OS X with partial Linux support.
|
99
|
+
|
100
|
+
Cron scheduling is partially implemented with [whenever](https://github.com/javan/whenever),
|
101
|
+
and other extpass methods like a password file would be helpful.
|
102
|
+
|
103
|
+
## Contributing
|
104
|
+
|
105
|
+
* [Fork](https://help.github.com/articles/fork-a-repo)
|
106
|
+
* Create a topic branch - `git checkout -b my_branch`
|
107
|
+
* Push to your branch - `git push origin my_branch`
|
108
|
+
* Create a [pull request](http://help.github.com/pull-requests/) from your branch
|
109
|
+
|
110
|
+
Please add a changelog entry for new features and bug fixes.
|
111
|
+
|
112
|
+
Writing specs will get your code pulled faster.
|
113
|
+
|
114
|
+
## Roadmap
|
115
|
+
|
116
|
+
This is the list of planned features/changes:
|
117
|
+
|
118
|
+
* Complete test suite.
|
119
|
+
* Get password from a file.
|
120
|
+
* Cron scheduling with [whenever](https://github.com/javan/whenever).
|
4
121
|
|
5
122
|
## Meta
|
6
123
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0
|
1
|
+
0.1.0
|
data/bin/boxafe
CHANGED
data/lib/boxafe/box.rb
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
class Boxafe::Box
|
5
|
+
|
6
|
+
OPTION_KEYS = [ :name, :root, :mount, :volume, :config, :keychain ]
|
7
|
+
|
8
|
+
def initialize options = {}
|
9
|
+
|
10
|
+
raise Boxafe::Error, "The :name option is required" unless options[:name]
|
11
|
+
|
12
|
+
@options = options
|
13
|
+
end
|
14
|
+
|
15
|
+
def name
|
16
|
+
@options[:name]
|
17
|
+
end
|
18
|
+
|
19
|
+
def mount
|
20
|
+
system encfs.command
|
21
|
+
end
|
22
|
+
|
23
|
+
def unmount
|
24
|
+
opts = options
|
25
|
+
result = system "#{opts[:umount]} #{opts[:mount]}"
|
26
|
+
sleep opts[:umount_delay] if opts[:umount_delay] and opts[:umount_delay] > 0
|
27
|
+
result
|
28
|
+
end
|
29
|
+
|
30
|
+
def encfs
|
31
|
+
Boxafe::Encfs.new options
|
32
|
+
end
|
33
|
+
|
34
|
+
def ensure_mount_point
|
35
|
+
FileUtils.mkdir_p options[:mount]
|
36
|
+
end
|
37
|
+
|
38
|
+
def description verbose = false
|
39
|
+
opts = options
|
40
|
+
String.new.tap do |s|
|
41
|
+
|
42
|
+
s << Paint["## #{name}", :cyan, :bold]
|
43
|
+
s << "\nEncrypted Root: "
|
44
|
+
s << if File.directory?(opts[:root])
|
45
|
+
Paint["#{opts[:root]}", :green]
|
46
|
+
elsif File.exists?(opts[:root])
|
47
|
+
Paint["#{opts[:root]} (not a directory)", :red]
|
48
|
+
else
|
49
|
+
Paint["#{opts[:root]} (doesn't exist)", :red]
|
50
|
+
end
|
51
|
+
|
52
|
+
s << "\nMount Point: "
|
53
|
+
s << case mount_status
|
54
|
+
when :mounted
|
55
|
+
Paint["#{opts[:mount]}", :green]
|
56
|
+
when :invalid
|
57
|
+
Paint["#{opts[:mount]} (not a directory)", :red]
|
58
|
+
else
|
59
|
+
Paint["#{opts[:mount]} (not mounted)", :yellow]
|
60
|
+
end
|
61
|
+
|
62
|
+
s << "\nVolume Name: #{opts[:volume]}"
|
63
|
+
s << "\nKeychain Password: #{opts[:keychain]}" if opts[:keychain]
|
64
|
+
s << "\nEncFS Config: #{opts[:config]}" if opts[:config]
|
65
|
+
|
66
|
+
s << "\nCommand: #{Paint[encfs.command, :yellow]}" if verbose
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def mount_status
|
71
|
+
if File.directory? options[:mount]
|
72
|
+
:mounted
|
73
|
+
elsif File.exists? options[:mount]
|
74
|
+
:invalid
|
75
|
+
else
|
76
|
+
:unmounted
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def configure options = {}, &block
|
81
|
+
@options.merge! options
|
82
|
+
DSL.new(@options).instance_eval &block if block
|
83
|
+
self
|
84
|
+
end
|
85
|
+
|
86
|
+
def options
|
87
|
+
@options.tap do |opts|
|
88
|
+
opts[:root] = File.expand_path opts[:root] || "~/Dropbox/#{opts[:name]}"
|
89
|
+
opts[:mount] = File.expand_path opts[:mount] || "/Volumes/#{opts[:name]}"
|
90
|
+
opts[:config] = File.expand_path opts[:config] if opts[:config]
|
91
|
+
opts[:volume] ||= opts[:name]
|
92
|
+
opts[:keychain] = opts[:name] if opts[:keychain] == true
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
class DSL
|
97
|
+
|
98
|
+
def initialize options
|
99
|
+
@options = options
|
100
|
+
end
|
101
|
+
|
102
|
+
OPTION_KEYS.each{ |name| define_method(name){ |value| @options[name] = value } }
|
103
|
+
end
|
104
|
+
end
|
data/lib/boxafe/cli.rb
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
class Boxafe::CLI
|
3
|
+
|
4
|
+
def start options = {}
|
5
|
+
# TODO: allow to mount only specific boxes
|
6
|
+
# TODO: only allow boxes with an extpass
|
7
|
+
Boxafe::Scheduler.platform_scheduler(options).start
|
8
|
+
end
|
9
|
+
|
10
|
+
def stop options = {}
|
11
|
+
Boxafe::Scheduler.platform_scheduler(options).stop
|
12
|
+
end
|
13
|
+
|
14
|
+
def status options = {}
|
15
|
+
|
16
|
+
config = load_config options
|
17
|
+
|
18
|
+
puts
|
19
|
+
puts Paint["# Boxafe v#{Boxafe::VERSION}", :bold]
|
20
|
+
|
21
|
+
config.boxes.each do |box|
|
22
|
+
puts
|
23
|
+
puts box.description(options[:verbose])
|
24
|
+
end
|
25
|
+
|
26
|
+
puts
|
27
|
+
end
|
28
|
+
|
29
|
+
def mount *args
|
30
|
+
|
31
|
+
options = args.last.kind_of?(Hash) ? args.pop : {}
|
32
|
+
config = load_config options
|
33
|
+
|
34
|
+
# FIXME: crashes with unknown box names
|
35
|
+
boxes = args.empty? ? config.boxes : args.collect{ |arg| config.boxes.find{ |box| box.name == arg } }
|
36
|
+
|
37
|
+
puts
|
38
|
+
boxes.each do |box|
|
39
|
+
|
40
|
+
print "Mounting #{box.name}... "
|
41
|
+
case box.mount_status
|
42
|
+
when :mounted
|
43
|
+
puts Paint['already mounted', :green]
|
44
|
+
next
|
45
|
+
when :invalid
|
46
|
+
puts Paint['invalid mount point', :red]
|
47
|
+
next
|
48
|
+
end
|
49
|
+
|
50
|
+
box.ensure_mount_point
|
51
|
+
box.mount
|
52
|
+
|
53
|
+
puts case box.mount_status
|
54
|
+
when :mounted
|
55
|
+
Paint['mounted', :green]
|
56
|
+
else
|
57
|
+
Paint['could not be mounted', :red]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
puts
|
62
|
+
end
|
63
|
+
|
64
|
+
def unmount *args
|
65
|
+
|
66
|
+
options = args.last.kind_of?(Hash) ? args.pop : {}
|
67
|
+
config = load_config options
|
68
|
+
|
69
|
+
boxes = args.empty? ? config.boxes : args.collect{ |arg| config.boxes.find{ |box| box.name == arg } }
|
70
|
+
|
71
|
+
puts
|
72
|
+
boxes.each do |box|
|
73
|
+
|
74
|
+
print "Umounting #{box.name}... "
|
75
|
+
box.unmount
|
76
|
+
|
77
|
+
puts case box.mount_status
|
78
|
+
when :unmounted
|
79
|
+
Paint['unmounted', :green]
|
80
|
+
else
|
81
|
+
Paint['could not be unmounted', :red]
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
puts
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
def load_config options = {}
|
91
|
+
Boxafe::Config.new(options).load
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
class Boxafe::Config
|
3
|
+
|
4
|
+
# TODO: document unmount_delay
|
5
|
+
OPTION_KEYS = [ :encfs, :umount, :umount_delay ]
|
6
|
+
|
7
|
+
attr_reader :boxes, :options
|
8
|
+
|
9
|
+
def initialize options = {}
|
10
|
+
@boxes = []
|
11
|
+
@options = { encfs: 'encfs', umount: 'umount', umount_delay: 0.5 }.merge options
|
12
|
+
end
|
13
|
+
|
14
|
+
def configure file = nil, &block
|
15
|
+
DSL.new(self).tap do |dsl|
|
16
|
+
dsl.instance_eval File.read(file), file if file
|
17
|
+
dsl.instance_eval &block if block
|
18
|
+
end
|
19
|
+
self
|
20
|
+
end
|
21
|
+
|
22
|
+
def load
|
23
|
+
configure file
|
24
|
+
end
|
25
|
+
|
26
|
+
def file
|
27
|
+
File.expand_path [ @options[:config], ENV['BOXAFE_CONFIG'], "~/.boxafe.rb" ].compact.first
|
28
|
+
end
|
29
|
+
|
30
|
+
class DSL
|
31
|
+
|
32
|
+
def initialize config
|
33
|
+
@config = config
|
34
|
+
end
|
35
|
+
|
36
|
+
def box options = {}, &block
|
37
|
+
Boxafe::Box.new(@config.options.merge(options)).tap do |box|
|
38
|
+
@config.boxes << box.configure(&block)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def env *args
|
43
|
+
Mutaconf.env *args
|
44
|
+
end
|
45
|
+
|
46
|
+
OPTION_KEYS.each do |name|
|
47
|
+
define_method(name){ |value| @config.options[name.to_sym] = value }
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/lib/boxafe/encfs.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
class Boxafe::Encfs
|
5
|
+
|
6
|
+
def initialize options = {}
|
7
|
+
@options = options
|
8
|
+
end
|
9
|
+
|
10
|
+
def command
|
11
|
+
[ encfs_config, @options[:encfs], %/"#{@options[:root]}"/, %/"#{@options[:mount]}"/, extpass, '--', volname ].compact.join ' '
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def volname
|
17
|
+
%/-ovolname="#{@options[:volume]}"/
|
18
|
+
end
|
19
|
+
|
20
|
+
def extpass
|
21
|
+
if @options[:keychain]
|
22
|
+
%*--extpass="security 2>&1 >/dev/null find-generic-password -gl '#{@options[:keychain]}' |grep password|cut -d \\\\\\" -f 2"*
|
23
|
+
else
|
24
|
+
nil
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def encfs_config
|
29
|
+
@options[:encfs_config] ? %/ENCFS6_CONFIG="#{File.expand_path @options[:encfs_config]}"/ : nil
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'commander'
|
3
|
+
|
4
|
+
class Boxafe::Program < Commander::Runner
|
5
|
+
|
6
|
+
GLOBAL_OPTIONS = [ :config, :verbose ]
|
7
|
+
BACKTRACE_NOTICE = ' (use --trace to view backtrace)'
|
8
|
+
|
9
|
+
include Commander::UI
|
10
|
+
include Commander::UI::AskForClass
|
11
|
+
|
12
|
+
def initialize argv = ARGV
|
13
|
+
super argv
|
14
|
+
|
15
|
+
program :name, 'boxafe'
|
16
|
+
program :version, Boxafe::VERSION
|
17
|
+
program :description, 'Secure your Dropbox with encfs.'
|
18
|
+
|
19
|
+
global_option '-c', '--config PATH', 'Use a custom configuration file (defaults to ~/.boxafe.rb)'
|
20
|
+
global_option '--verbose', 'Increase verbosity'
|
21
|
+
|
22
|
+
command :status do |c|
|
23
|
+
c.syntax = 'boxafe status'
|
24
|
+
c.description = 'Display the current status and configuration'
|
25
|
+
c.action do |args,options|
|
26
|
+
to_trace_or_not_to_trace do
|
27
|
+
cli.status extract(options)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
command :mount do |c|
|
33
|
+
c.syntax = 'boxafe mount'
|
34
|
+
c.description = 'Mount configured boxes with EncFS'
|
35
|
+
c.action do |args,options|
|
36
|
+
to_trace_or_not_to_trace do
|
37
|
+
cli.mount *args
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
command :unmount do |c|
|
43
|
+
c.syntax = 'boxafe unmount'
|
44
|
+
c.description = 'Unmount configured boxes'
|
45
|
+
c.action do |args,options|
|
46
|
+
to_trace_or_not_to_trace do
|
47
|
+
cli.unmount *args
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
command :start do |c|
|
53
|
+
c.syntax = 'boxafe start'
|
54
|
+
c.description = 'Configure boxafe to run on startup'
|
55
|
+
c.action do |args,options|
|
56
|
+
to_trace_or_not_to_trace do
|
57
|
+
cli.start *(args.push extract(options))
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
command :stop do |c|
|
63
|
+
c.syntax = 'boxafe stop'
|
64
|
+
c.description = 'Stop boxafe from running on startup'
|
65
|
+
c.action do |args,options|
|
66
|
+
to_trace_or_not_to_trace do
|
67
|
+
cli.stop *(args.push extract(options))
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def cli
|
76
|
+
Boxafe::CLI.new
|
77
|
+
end
|
78
|
+
|
79
|
+
def to_trace_or_not_to_trace trace = false
|
80
|
+
begin
|
81
|
+
yield
|
82
|
+
rescue Boxafe::Error => e
|
83
|
+
if trace
|
84
|
+
raise e
|
85
|
+
else
|
86
|
+
warn Paint["#{e.message}#{BACKTRACE_NOTICE}", :red]
|
87
|
+
exit e.code
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def extract *args
|
93
|
+
options = args.pop
|
94
|
+
(args | GLOBAL_OPTIONS).inject({}){ |memo,k| memo[k] = options.__send__(k); memo }.reject{ |k,v| v.nil? }
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
#require 'whenever'
|
3
|
+
|
4
|
+
class Boxafe::Scheduler::Cron < Boxafe::Scheduler
|
5
|
+
|
6
|
+
def start
|
7
|
+
raise 'Not yet implemented on this operating system'
|
8
|
+
Whenever::CommandLine.execute block: mount_schedule, write: true, identifier: 'boxafe-mount'
|
9
|
+
end
|
10
|
+
|
11
|
+
def stop
|
12
|
+
raise 'Not yet implemented on this operating system'
|
13
|
+
Whenever::CommandLine.execute block: mount_schedule, clear: true, identifier: 'boxafe-mount'
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def self.mount_schedule
|
19
|
+
Proc.new do
|
20
|
+
every 1.minute do
|
21
|
+
command 'echo $(date) > /Users/unknow/Projects/boxafe/bar.txt'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'launchdr'
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
class Boxafe::Scheduler::Launchd < Boxafe::Scheduler
|
6
|
+
|
7
|
+
def start
|
8
|
+
stop
|
9
|
+
plist.dump USER_AGENT
|
10
|
+
plist.load!
|
11
|
+
end
|
12
|
+
|
13
|
+
def stop
|
14
|
+
return false unless plist_exists?
|
15
|
+
plist.unload!
|
16
|
+
FileUtils.rm_f plist.file
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
LABEL = 'com.alphahydrae.boxafe'
|
22
|
+
USER_AGENT = LaunchDr::Launchd::Paths[:user_agent]
|
23
|
+
|
24
|
+
def plist_exists?
|
25
|
+
begin
|
26
|
+
File.exists? plist.file
|
27
|
+
rescue
|
28
|
+
false
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def plist
|
33
|
+
@plist ||= LaunchDr::Launchd.new(LABEL).tap do |plist|
|
34
|
+
plist[:ProgramArguments] = [ 'boxafe', 'mount' ]
|
35
|
+
plist[:RunAtLoad] = true
|
36
|
+
plist[:EnvironmentVariables] = { 'PATH' => ENV['PATH'] } # TODO: add path option
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
class Boxafe::Scheduler
|
3
|
+
|
4
|
+
def self.platform_scheduler options = {}
|
5
|
+
case RbConfig::CONFIG['host_os']
|
6
|
+
when /darwin/i
|
7
|
+
Boxafe::Scheduler::Launchd.new options
|
8
|
+
else
|
9
|
+
Boxafe::Scheduler::Cron.new options
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize options = {}
|
14
|
+
@options = options
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
Dir[File.join File.dirname(__FILE__), File.basename(__FILE__, '.*'), '*.rb'].each{ |lib| require lib }
|
data/lib/boxafe.rb
CHANGED
@@ -1,8 +1,20 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
require 'paint'
|
3
|
+
require 'dotenv'
|
4
|
+
require 'mutaconf'
|
3
5
|
|
4
6
|
module Boxafe
|
5
|
-
VERSION = '0.0
|
7
|
+
VERSION = '0.1.0'
|
8
|
+
|
9
|
+
# TODO: add detailed error description for non-trace mode
|
10
|
+
class Error < StandardError
|
11
|
+
attr_reader :code
|
12
|
+
|
13
|
+
def initialize msg, code = 1
|
14
|
+
super msg
|
15
|
+
@code = code
|
16
|
+
end
|
17
|
+
end
|
6
18
|
end
|
7
19
|
|
8
20
|
Dir[File.join File.dirname(__FILE__), File.basename(__FILE__, '.*'), '*.rb'].each{ |lib| require lib }
|
metadata
CHANGED
@@ -1,18 +1,20 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: boxafe
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
5
6
|
platform: ruby
|
6
7
|
authors:
|
7
|
-
- AlphaHydrae
|
8
|
+
- Simon Oulevay (AlphaHydrae)
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date: 2013-
|
12
|
+
date: 2013-07-09 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
15
|
name: paint
|
15
16
|
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
16
18
|
requirements:
|
17
19
|
- - ~>
|
18
20
|
- !ruby/object:Gem::Version
|
@@ -20,6 +22,7 @@ dependencies:
|
|
20
22
|
type: :runtime
|
21
23
|
prerelease: false
|
22
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
23
26
|
requirements:
|
24
27
|
- - ~>
|
25
28
|
- !ruby/object:Gem::Version
|
@@ -27,6 +30,7 @@ dependencies:
|
|
27
30
|
- !ruby/object:Gem::Dependency
|
28
31
|
name: commander
|
29
32
|
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
30
34
|
requirements:
|
31
35
|
- - ~>
|
32
36
|
- !ruby/object:Gem::Version
|
@@ -34,183 +38,118 @@ dependencies:
|
|
34
38
|
type: :runtime
|
35
39
|
prerelease: false
|
36
40
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
37
42
|
requirements:
|
38
43
|
- - ~>
|
39
44
|
- !ruby/object:Gem::Version
|
40
45
|
version: 4.1.2
|
41
46
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
47
|
+
name: which_works
|
43
48
|
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
44
50
|
requirements:
|
45
51
|
- - ~>
|
46
52
|
- !ruby/object:Gem::Version
|
47
|
-
version: 0.
|
53
|
+
version: 1.0.0
|
48
54
|
type: :runtime
|
49
55
|
prerelease: false
|
50
56
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
51
58
|
requirements:
|
52
59
|
- - ~>
|
53
60
|
- !ruby/object:Gem::Version
|
54
|
-
version: 0.
|
61
|
+
version: 1.0.0
|
55
62
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
63
|
+
name: dotenv
|
57
64
|
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
58
66
|
requirements:
|
59
|
-
- -
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '0'
|
62
|
-
type: :development
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - '>='
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: '0'
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: rake
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
72
|
-
requirements:
|
73
|
-
- - '>='
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version: '0'
|
76
|
-
type: :development
|
77
|
-
prerelease: false
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
79
|
-
requirements:
|
80
|
-
- - '>='
|
81
|
-
- !ruby/object:Gem::Version
|
82
|
-
version: '0'
|
83
|
-
- !ruby/object:Gem::Dependency
|
84
|
-
name: rspec
|
85
|
-
requirement: !ruby/object:Gem::Requirement
|
86
|
-
requirements:
|
87
|
-
- - '>='
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
version: '0'
|
90
|
-
type: :development
|
91
|
-
prerelease: false
|
92
|
-
version_requirements: !ruby/object:Gem::Requirement
|
93
|
-
requirements:
|
94
|
-
- - '>='
|
95
|
-
- !ruby/object:Gem::Version
|
96
|
-
version: '0'
|
97
|
-
- !ruby/object:Gem::Dependency
|
98
|
-
name: jeweler
|
99
|
-
requirement: !ruby/object:Gem::Requirement
|
100
|
-
requirements:
|
101
|
-
- - '>='
|
102
|
-
- !ruby/object:Gem::Version
|
103
|
-
version: '0'
|
104
|
-
type: :development
|
105
|
-
prerelease: false
|
106
|
-
version_requirements: !ruby/object:Gem::Requirement
|
107
|
-
requirements:
|
108
|
-
- - '>='
|
109
|
-
- !ruby/object:Gem::Version
|
110
|
-
version: '0'
|
111
|
-
- !ruby/object:Gem::Dependency
|
112
|
-
name: gemcutter
|
113
|
-
requirement: !ruby/object:Gem::Requirement
|
114
|
-
requirements:
|
115
|
-
- - '>='
|
116
|
-
- !ruby/object:Gem::Version
|
117
|
-
version: '0'
|
118
|
-
type: :development
|
119
|
-
prerelease: false
|
120
|
-
version_requirements: !ruby/object:Gem::Requirement
|
121
|
-
requirements:
|
122
|
-
- - '>='
|
123
|
-
- !ruby/object:Gem::Version
|
124
|
-
version: '0'
|
125
|
-
- !ruby/object:Gem::Dependency
|
126
|
-
name: gem-release
|
127
|
-
requirement: !ruby/object:Gem::Requirement
|
128
|
-
requirements:
|
129
|
-
- - '>='
|
67
|
+
- - ~>
|
130
68
|
- !ruby/object:Gem::Version
|
131
|
-
version:
|
132
|
-
type: :
|
69
|
+
version: 0.8.0
|
70
|
+
type: :runtime
|
133
71
|
prerelease: false
|
134
72
|
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
135
74
|
requirements:
|
136
|
-
- -
|
75
|
+
- - ~>
|
137
76
|
- !ruby/object:Gem::Version
|
138
|
-
version:
|
77
|
+
version: 0.8.0
|
139
78
|
- !ruby/object:Gem::Dependency
|
140
|
-
name:
|
79
|
+
name: mutaconf
|
141
80
|
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
142
82
|
requirements:
|
143
|
-
- -
|
83
|
+
- - ~>
|
144
84
|
- !ruby/object:Gem::Version
|
145
|
-
version:
|
146
|
-
type: :
|
85
|
+
version: 0.2.0
|
86
|
+
type: :runtime
|
147
87
|
prerelease: false
|
148
88
|
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
149
90
|
requirements:
|
150
|
-
- -
|
91
|
+
- - ~>
|
151
92
|
- !ruby/object:Gem::Version
|
152
|
-
version:
|
93
|
+
version: 0.2.0
|
153
94
|
- !ruby/object:Gem::Dependency
|
154
|
-
name:
|
95
|
+
name: launchdr
|
155
96
|
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
156
98
|
requirements:
|
157
|
-
- - '
|
99
|
+
- - '='
|
158
100
|
- !ruby/object:Gem::Version
|
159
|
-
version: '
|
160
|
-
type: :
|
101
|
+
version: '3'
|
102
|
+
type: :runtime
|
161
103
|
prerelease: false
|
162
104
|
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
163
106
|
requirements:
|
164
|
-
- - '
|
107
|
+
- - '='
|
165
108
|
- !ruby/object:Gem::Version
|
166
|
-
version: '
|
167
|
-
description: Boxafe
|
168
|
-
|
169
|
-
|
170
|
-
|
109
|
+
version: '3'
|
110
|
+
description: Boxafe mounts EncFS filesystems or "boxes" that you define in a configuration
|
111
|
+
file with a friendly DSL.
|
112
|
+
email: contact@alphahydrae.com
|
113
|
+
executables: []
|
171
114
|
extensions: []
|
172
|
-
extra_rdoc_files:
|
173
|
-
- LICENSE.txt
|
174
|
-
- README.md
|
115
|
+
extra_rdoc_files: []
|
175
116
|
files:
|
176
|
-
-
|
177
|
-
- .
|
178
|
-
- .
|
179
|
-
- .
|
180
|
-
- .
|
181
|
-
-
|
182
|
-
-
|
117
|
+
- bin/boxafe
|
118
|
+
- lib/boxafe.rb
|
119
|
+
- lib/boxafe/box.rb
|
120
|
+
- lib/boxafe/cli.rb
|
121
|
+
- lib/boxafe/config.rb
|
122
|
+
- lib/boxafe/encfs.rb
|
123
|
+
- lib/boxafe/program.rb
|
124
|
+
- lib/boxafe/scheduler.rb
|
125
|
+
- lib/boxafe/scheduler/cron.rb
|
126
|
+
- lib/boxafe/scheduler/launchd.rb
|
183
127
|
- LICENSE.txt
|
184
128
|
- README.md
|
185
|
-
- Rakefile
|
186
129
|
- VERSION
|
187
|
-
- bin/boxafe
|
188
|
-
- lib/boxafe.rb
|
189
|
-
- lib/program.rb
|
190
|
-
- spec/helper.rb
|
191
|
-
- spec/version_spec.rb
|
192
130
|
homepage: http://github.com/AlphaHydrae/boxafe
|
193
131
|
licenses:
|
194
132
|
- MIT
|
195
|
-
metadata: {}
|
196
133
|
post_install_message:
|
197
134
|
rdoc_options: []
|
198
135
|
require_paths:
|
199
136
|
- lib
|
200
137
|
required_ruby_version: !ruby/object:Gem::Requirement
|
138
|
+
none: false
|
201
139
|
requirements:
|
202
|
-
- - '>='
|
140
|
+
- - ! '>='
|
203
141
|
- !ruby/object:Gem::Version
|
204
142
|
version: '0'
|
205
143
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
144
|
+
none: false
|
206
145
|
requirements:
|
207
|
-
- - '>='
|
146
|
+
- - ! '>='
|
208
147
|
- !ruby/object:Gem::Version
|
209
148
|
version: '0'
|
210
149
|
requirements: []
|
211
150
|
rubyforge_project:
|
212
|
-
rubygems_version:
|
151
|
+
rubygems_version: 1.8.25
|
213
152
|
signing_key:
|
214
|
-
specification_version:
|
215
|
-
summary: Secure your Dropbox with
|
153
|
+
specification_version: 3
|
154
|
+
summary: Secure your Dropbox with EncFS.
|
216
155
|
test_files: []
|
checksums.yaml
DELETED
@@ -1,7 +0,0 @@
|
|
1
|
-
---
|
2
|
-
SHA1:
|
3
|
-
metadata.gz: 4de5c77095d8c7c91c9b6169b98c67b020e2d397
|
4
|
-
data.tar.gz: cd7ea69c1b18cd33717a5f1fc02e42752aee9f16
|
5
|
-
SHA512:
|
6
|
-
metadata.gz: 512a2e21e634c9d949eee1c3c27e691e96e58040f55995ba9535b94fb026ff44111faf925a22031819be4dcf1c3d171eb4de105a0dda45b4315a0c431d9e8f28
|
7
|
-
data.tar.gz: 1e6c18d68ab00611a7ca82c62023df3e5e3691c7df775ca58245f1de108d6ecd68617e4701379fa97da8993aa6c7bd225d6c37171f2d2bc26b19deb4cf0e56ec
|
data/.rspec
DELETED
data/.ruby-gemset
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
boxafe
|
data/.ruby-version
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
2.0.0
|
data/.screenrc
DELETED
data/.travis.yml
DELETED
data/Gemfile
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
source "http://rubygems.org"
|
2
|
-
# Add dependencies required to use your gem here.
|
3
|
-
# Example:
|
4
|
-
# gem "activesupport", ">= 2.3.5"
|
5
|
-
|
6
|
-
gem 'paint', '~> 0.8.5'
|
7
|
-
gem 'commander', '~> 4.1.2'
|
8
|
-
gem 'whenever', '~> 0.8.2'
|
9
|
-
|
10
|
-
# Add dependencies to develop your gem here.
|
11
|
-
# Include everything needed to run rake, tests, features, etc.
|
12
|
-
group :development do
|
13
|
-
gem 'bundler'
|
14
|
-
gem 'rake'
|
15
|
-
gem 'rspec'
|
16
|
-
gem 'jeweler'
|
17
|
-
gem 'gemcutter'
|
18
|
-
gem 'gem-release'
|
19
|
-
gem 'rake-version'
|
20
|
-
gem 'simplecov'
|
21
|
-
end
|
data/Gemfile.lock
DELETED
@@ -1,59 +0,0 @@
|
|
1
|
-
GEM
|
2
|
-
remote: http://rubygems.org/
|
3
|
-
specs:
|
4
|
-
activesupport (3.2.13)
|
5
|
-
i18n (= 0.6.1)
|
6
|
-
multi_json (~> 1.0)
|
7
|
-
chronic (0.9.1)
|
8
|
-
commander (4.1.3)
|
9
|
-
highline (~> 1.6.11)
|
10
|
-
diff-lcs (1.2.2)
|
11
|
-
gem-release (0.5.3)
|
12
|
-
gemcutter (0.7.1)
|
13
|
-
git (1.2.5)
|
14
|
-
highline (1.6.16)
|
15
|
-
i18n (0.6.1)
|
16
|
-
jeweler (1.8.4)
|
17
|
-
bundler (~> 1.0)
|
18
|
-
git (>= 1.2.5)
|
19
|
-
rake
|
20
|
-
rdoc
|
21
|
-
json (1.7.7)
|
22
|
-
multi_json (1.7.2)
|
23
|
-
paint (0.8.5)
|
24
|
-
rake (10.0.4)
|
25
|
-
rake-version (0.3.1)
|
26
|
-
rake (~> 10)
|
27
|
-
rdoc (4.0.1)
|
28
|
-
json (~> 1.4)
|
29
|
-
rspec (2.13.0)
|
30
|
-
rspec-core (~> 2.13.0)
|
31
|
-
rspec-expectations (~> 2.13.0)
|
32
|
-
rspec-mocks (~> 2.13.0)
|
33
|
-
rspec-core (2.13.1)
|
34
|
-
rspec-expectations (2.13.0)
|
35
|
-
diff-lcs (>= 1.1.3, < 2.0)
|
36
|
-
rspec-mocks (2.13.1)
|
37
|
-
simplecov (0.7.1)
|
38
|
-
multi_json (~> 1.0)
|
39
|
-
simplecov-html (~> 0.7.1)
|
40
|
-
simplecov-html (0.7.1)
|
41
|
-
whenever (0.8.2)
|
42
|
-
activesupport (>= 2.3.4)
|
43
|
-
chronic (>= 0.6.3)
|
44
|
-
|
45
|
-
PLATFORMS
|
46
|
-
ruby
|
47
|
-
|
48
|
-
DEPENDENCIES
|
49
|
-
bundler
|
50
|
-
commander (~> 4.1.2)
|
51
|
-
gem-release
|
52
|
-
gemcutter
|
53
|
-
jeweler
|
54
|
-
paint (~> 0.8.5)
|
55
|
-
rake
|
56
|
-
rake-version
|
57
|
-
rspec
|
58
|
-
simplecov
|
59
|
-
whenever (~> 0.8.2)
|
data/Rakefile
DELETED
@@ -1,51 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
require 'rubygems'
|
4
|
-
require 'bundler'
|
5
|
-
begin
|
6
|
-
Bundler.setup(:default, :development)
|
7
|
-
rescue Bundler::BundlerError => e
|
8
|
-
$stderr.puts e.message
|
9
|
-
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
-
exit e.status_code
|
11
|
-
end
|
12
|
-
require 'rake'
|
13
|
-
|
14
|
-
require 'jeweler'
|
15
|
-
Jeweler::Tasks.new do |gem|
|
16
|
-
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
17
|
-
gem.name = "boxafe"
|
18
|
-
gem.homepage = "http://github.com/AlphaHydrae/boxafe"
|
19
|
-
gem.license = "MIT"
|
20
|
-
gem.summary = %Q{Secure your Dropbox with encfs.}
|
21
|
-
gem.description = %Q{Boxafe encrypts and auto-mounts a folder with encfs and whenever.}
|
22
|
-
gem.email = "hydrae.alpha@gmail.com"
|
23
|
-
gem.authors = ["AlphaHydrae"]
|
24
|
-
# dependencies defined in Gemfile
|
25
|
-
end
|
26
|
-
Jeweler::RubygemsDotOrgTasks.new
|
27
|
-
|
28
|
-
Rake::TaskManager.class_eval do
|
29
|
-
def remove_task(task_name)
|
30
|
-
@tasks.delete(task_name.to_s)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
[ 'version', 'version:bump:major', 'version:bump:minor', 'version:bump:patch', 'version:write' ].each do |task|
|
35
|
-
Rake.application.remove_task task
|
36
|
-
end
|
37
|
-
|
38
|
-
# version tasks
|
39
|
-
require 'rake-version'
|
40
|
-
RakeVersion::Tasks.new do |v|
|
41
|
-
v.copy 'lib/boxafe.rb'
|
42
|
-
end
|
43
|
-
|
44
|
-
require 'rspec/core/rake_task'
|
45
|
-
desc "Run specs"
|
46
|
-
RSpec::Core::RakeTask.new do |t|
|
47
|
-
#t.pattern = "./spec/**/*_spec.rb" # don't need this, it's default.
|
48
|
-
# Put spec opts in a file named .rspec in root
|
49
|
-
end
|
50
|
-
|
51
|
-
task :default => :spec
|
data/lib/program.rb
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
require File.join File.dirname(__FILE__), 'boxafe'
|
2
|
-
require 'commander/import'
|
3
|
-
|
4
|
-
program :name, 'boxafe'
|
5
|
-
program :version, Boxafe::VERSION
|
6
|
-
program :description, 'Secure your Dropbox with encfs.'
|
7
|
-
|
8
|
-
#global_option '-c', '--config PATH', 'Use a custom configuration file (defaults to ~/.boxafe.rb)'
|
9
|
-
|
10
|
-
command :info do |c|
|
11
|
-
c.syntax = 'boxafe info'
|
12
|
-
c.description = 'Display the current configuration (default action)'
|
13
|
-
c.action do |args,options|
|
14
|
-
puts 'Not yet implemented'
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
default_command :info
|
data/spec/helper.rb
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'bundler'
|
3
|
-
|
4
|
-
begin
|
5
|
-
Bundler.setup(:default, :development)
|
6
|
-
rescue Bundler::BundlerError => e
|
7
|
-
$stderr.puts e.message
|
8
|
-
$stderr.puts "Run `bundle install` to install missing gems"
|
9
|
-
exit e.status_code
|
10
|
-
end
|
11
|
-
|
12
|
-
require 'simplecov'
|
13
|
-
SimpleCov.start
|
14
|
-
|
15
|
-
require 'rspec'
|
16
|
-
require 'boxafe'
|