-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Arek Bochinski
committed
Jun 28, 2010
0 parents
commit c69b5ef
Showing
5 changed files
with
963 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
Requires : | ||
Fuse filesystem libraries. | ||
Install Fuse from here: http://fuse.sourceforge.net/ | ||
|
||
Python | ||
|
||
Uses: http://code.google.com/p/fusepy/ - Provided with this software. | ||
|
||
|
||
DropFuse limitations and capabilites: | ||
|
||
1). | ||
Uses an SGML html parser to extract the document information. | ||
This is hardly optimal, but I am not aware of any official API for the | ||
linked folder feature introduced by DropBox in client 0.8 | ||
|
||
2). | ||
It will mount the linked folder to a specified directory, but it will | ||
not refresh the mounted directory if the remote shared folder has been | ||
updated on DropBox servers. | ||
|
||
3). | ||
Once mounted, folder's contents can be easily copied to your local storage. | ||
No data is transferred until a copy is performed. | ||
Copy them to a local folder before using. | ||
Currently, copying process seems to rather slow. | ||
|
||
4). | ||
Reading nested subfolders is not supported yet. | ||
Only files located directly in linked folder are usable. | ||
|
||
5). | ||
Do not use the URL shortener service link provided by DropBox | ||
These links look like this: http://db.tt/bP1ntM and are not supported yet. | ||
Use the actual destination link which is usually shown in the browser's | ||
address bar. | ||
|
||
See README for instructions. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
DropFuse | ||
Copyright (C) 2010 Arek Bochinski | ||
|
||
This program is free software: you can redistribute it and/or modify | ||
it under the terms of the GNU General Public License as published by | ||
the Free Software Foundation, either version 3 of the License, or | ||
(at your option) any later version. | ||
|
||
This program is distributed in the hope that it will be useful, | ||
but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
GNU General Public License for more details. | ||
|
||
You should have received a copy of the GNU General Public License | ||
along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
|
||
|
||
Notice about this software's relation to DropBox.com: | ||
|
||
This software is not linked, authorized or supported by DropBox.com. | ||
Use it at own risk. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
1). Install: Fuse | ||
2). Get a link to a DropBox linked folder | ||
3). Extract the contents of this software and navigate to the software | ||
folder in command-line. | ||
4). Create an empty directory used during mounting the remote folder, | ||
for instance : mkdir mnt | ||
5). Run the command: | ||
python dropfuse.py <dropboc.com url> mnt/ | ||
|
||
To get you started, I have created a public folder link that you can | ||
test this on: | ||
|
||
https://www.dropbox.com/s/c6ecc2plwconh5x | ||
|
||
|
||
At this moment if everything goes well, you should see a drive mounted | ||
and named 'mnt'. Open it and use it in a file browser. | ||
|
||
To stop using the mounted drive type: | ||
fusermount -u mnt/ | ||
|
||
or: | ||
|
||
umount mnt/ | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,234 @@ | ||
#!/usr/bin/python | ||
# -*- coding: utf-8 -*- | ||
# author: Arek Bochinski , 2010, DropFuse - a linked DropBox folder filesystem | ||
# version: 0.1 | ||
# | ||
#See license note in COPYING document that must accompany this software | ||
|
||
#See CAPABILITIES for limitations of this software | ||
|
||
from fuse import * | ||
import urllib, sgmlib, re, os | ||
from sys import argv, exit | ||
|
||
from time import time | ||
from stat import S_IFDIR, S_IFLNK, S_IFREG | ||
from errno import ENOENT, EACCES | ||
|
||
|
||
class DropParser(sgmllib.SGMLParser): | ||
|
||
'''A simple parser for linked Dropbox folders.''' | ||
in_list = False | ||
d = 0 | ||
in_file_size = False | ||
in_modified = False | ||
in_list = False | ||
in_dir = False | ||
in_file = False | ||
cur_file = '' | ||
cur_dir = '' | ||
url = '' | ||
|
||
def parse(self, s): | ||
"""Parse the given string 's'.""" | ||
self.feed(s) | ||
self.close() | ||
self.in_list = False | ||
self.in_dir = False | ||
self.in_file = False | ||
self.in_file_size = False | ||
self.in_modified = False | ||
self.cur_file = '' | ||
self.cur_dir = '' | ||
self.url = '' | ||
|
||
def __init__(self, verbose=0): | ||
"""Initialise an object, passing 'verbose' to the superclass.""" | ||
sgmllib.SGMLParser.__init__(self, verbose) | ||
self.files = {} | ||
self.dirs = {} | ||
|
||
def handle_data(self, data): | ||
cldata = data.strip() | ||
|
||
if self.in_file_size: | ||
if len(cldata) > 0: | ||
self.in_file_size = False | ||
self.files[self.cur_file]['file_size'] = cldata | ||
elif self.in_modified: | ||
if len(cldata) > 0: | ||
self.in_modified = False | ||
self.files[self.cur_file]['modified'] = cldata | ||
|
||
def start_div(self, attributes): | ||
if self.in_file: | ||
for (name, value) in attributes: | ||
if name == 'class' and value == 'filesize': | ||
self.in_file_size = True | ||
self.in_modified = False | ||
elif name == 'class' and value == 'modified': | ||
self.in_file_size = False | ||
self.in_modified = True | ||
|
||
if self.in_list: | ||
self.d += 1 | ||
return | ||
for (name, value) in attributes: | ||
if name == 'id' and value == 'list-browser': | ||
self.d += 1 | ||
self.in_list = True | ||
|
||
def end_div(self): | ||
if self.in_list: | ||
self.d -= 1 | ||
|
||
if self.d <= 0: | ||
self.in_list = False | ||
|
||
def start_a(self, attributes): | ||
"""Process a hyperlink and its 'attributes'.""" | ||
self.in_dir = False | ||
self.in_file = False | ||
|
||
for (name, value) in attributes: | ||
if name == 'href' and value != '#': | ||
if self.in_list: | ||
if re.search('v=l$', value): | ||
self.in_dir = True | ||
self.in_file = False | ||
self.dirs[value] = {'name': value} | ||
self.cur_dir = value | ||
else: | ||
self.in_file = True | ||
self.in_dir = False | ||
self.files[value] = {'name': value} | ||
self.cur_file = value | ||
|
||
def get_dirs(self): | ||
'''Return the list of dirs.''' | ||
return self.dirs | ||
|
||
def get_files(self): | ||
'''Return the list of files.''' | ||
return self.files | ||
|
||
|
||
class DropFuse(Operations): | ||
|
||
def __init__(self, host, path=''): | ||
self.client = DropParser() | ||
self.client.url = host | ||
self.root = path | ||
f = \ | ||
urllib.urlopen('https://www.dropbox.com/s/c6ecc2plwconh5x#view:list' | ||
) | ||
s = f.read() | ||
self.now = time() | ||
self.client.parse(s) | ||
|
||
|
||
def getattr(self, path, fh=None): | ||
uid = pwd.getpwuid(os.getuid()).pw_uid | ||
gid = pwd.getpwuid(os.getuid()).pw_gid | ||
now = time() | ||
for dir in self.client.get_dirs(): | ||
if path == '/%s' \ | ||
% urllib.unquote(os.path.basename(dir).split('?')[0]): | ||
return dict( | ||
st_mode=S_IFDIR | 0755, | ||
st_ctime=now, | ||
st_mtime=now, | ||
st_atime=now, | ||
st_nlink=2, | ||
st_uid=uid, | ||
st_gid=gid, | ||
) | ||
for fl in self.client.get_files(): | ||
if path == '/%s' % urllib.unquote(os.path.basename(fl)): | ||
return dict( | ||
st_mode=S_IFREG | 0444, | ||
st_size=int(self.client.get_files()[fl]['file_size' | ||
]), | ||
st_ctime=self.now, | ||
st_mtime=self.now, | ||
st_atime=self.now, | ||
st_nlink=1, | ||
) | ||
if path == '/': | ||
return dict(st_mode=S_IFDIR | 0755, st_ctime=now, | ||
st_mtime=now, st_atime=now, st_nlink=3) | ||
else: | ||
return dict( | ||
st_mode=S_IFREG | 0444, | ||
st_size=0, | ||
st_ctime=now, | ||
st_mtime=now, | ||
st_atime=now, | ||
st_nlink=1, | ||
) | ||
|
||
def mkdir(self, path): | ||
pass | ||
|
||
def mknod( | ||
self, | ||
path, | ||
mode, | ||
dev, | ||
): | ||
return 0 | ||
|
||
def create(self, path, mode): | ||
return 0 | ||
|
||
def open(self, path, flags): | ||
return 0 | ||
|
||
def readdir(self, path, fh): | ||
defaults = ['.', '..'] | ||
if path == '/': | ||
for fl in self.client.get_files(): | ||
defaults.append(urllib.unquote(os.path.basename(fl))) | ||
|
||
for dir in self.client.get_dirs(): | ||
defaults.append('%s/' | ||
% urllib.unquote(os.path.basename(dir).split('?' | ||
)[0])) | ||
|
||
return defaults | ||
|
||
def read( | ||
self, | ||
path, | ||
size, | ||
offset, | ||
fh, | ||
): | ||
|
||
data = self.get_file(path) | ||
if data == None: | ||
return 0 | ||
if offset + size > len(data): | ||
size = len(data) - offset | ||
|
||
return data[offset:offset + size] | ||
|
||
def get_file(self, path): | ||
for fl in self.client.get_files(): | ||
if path == '/%s' % urllib.unquote(os.path.basename(fl)): | ||
url=fl.replace("www.dropbox.com","dl-web.dropbox.com") | ||
return urllib.urlopen(url).read() | ||
|
||
|
||
if __name__ == '__main__': | ||
if len(argv) != 3: | ||
print 'usage: %s <dropbox link> <mount point>' % argv[0] | ||
exit(1) | ||
|
||
link = argv[1] | ||
if re.match("#view:list$",link)==None: | ||
link = "%s#view:list"%link | ||
|
||
dropfuse = FUSE(DropFuse(link, argv[2]), argv[2], | ||
foreground=True, nothreads=True) |
Oops, something went wrong.