boxafe 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Gem Version](https://badge.fury.io/rb/boxafe.png)](http://badge.fury.io/rb/boxafe)
|
4
|
+
[![Dependency Status](https://gemnasium.com/AlphaHydrae/boxafe.png)](https://gemnasium.com/AlphaHydrae/boxafe)
|
5
|
+
[![Build Status](https://secure.travis-ci.org/AlphaHydrae/boxafe.png)](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'
|