Python module providing an easy access to FileDropper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ffx-backup.py 4.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. #
  4. # Copyright (c) 2009, Thomas Jost <thomas.jost@gmail.com>
  5. #
  6. # Permission to use, copy, modify, and/or distribute this software for any
  7. # purpose with or without fee is hereby granted, provided that the above
  8. # copyright notice and this permission notice appear in all copies.
  9. #
  10. # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  11. # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  12. # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  13. # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  14. # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  15. # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  16. # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  17. # Regular expressions matching files and folders to exclude from the backup
  18. EXCLUDES = [
  19. "/Cache",
  20. "/OfflineCache/",
  21. "\.mfasl$",
  22. "/urlclassifier",
  23. "/lock$",
  24. "/parent.lock$",
  25. "/.parentlock$",
  26. ]
  27. import os, os.path, re, sys, tarfile, time
  28. from optparse import OptionParser
  29. # Parse command line
  30. parser = OptionParser()
  31. parser.add_option("-f", "--folder", dest="profile_path", help="profile folder to be saved")
  32. parser.add_option("-u", "--user", dest="fd_user", help="username for connection to FileDropper (optional)")
  33. parser.add_option("-p", "--password", dest="fd_pass", help="password for connection to FileDropper (optional)")
  34. parser.add_option("-c", "--crypt-to", dest="crypt_to", help="comma-separated list of recipients for GPG encryption of archive file (optional)")
  35. (options, args) = parser.parse_args()
  36. # Check if constraints are respected
  37. if options.profile_path is None:
  38. print "No profile specified"
  39. sys.exit(1)
  40. if (options.fd_user is not None and options.fd_pass is None) or (options.fd_user is None and options.fd_pass is not None):
  41. print "Username AND password needed"
  42. sys.exit(1)
  43. profile_name = os.path.basename(options.profile_path)
  44. date = time.strftime("%Y%m%d_%H%M%S")
  45. archive_name = "%s-%s.tar.bz2" % (profile_name, date)
  46. # Compile exclusion regexps
  47. EXCLUDES_RE = []
  48. for regexp in EXCLUDES:
  49. r = re.compile(regexp)
  50. EXCLUDES_RE.append(r)
  51. # Uncompressed size
  52. total_size = 0
  53. # Exclusion decision function
  54. def is_excluded(filename):
  55. global EXCLUDES_RE, total_size
  56. for regexp in EXCLUDES_RE:
  57. if regexp.search(filename):
  58. return True
  59. total_size += os.path.getsize(filename)
  60. return False
  61. # Open the destination tar archive
  62. tar = tarfile.open(archive_name, 'w:bz2')
  63. # Add the data to the archive
  64. tar.add(options.profile_path, profile_name, exclude=is_excluded)
  65. tar.close()
  66. # Display archive name and sizes
  67. print "Profile saved to %s" % archive_name
  68. archive_size = os.path.getsize(archive_name)
  69. print "%.1f MB --> %.1f MB" % (total_size/(1024**2), archive_size/(1024**2))
  70. # Encrypt the archive if needed
  71. if options.crypt_to is not None:
  72. import GnuPGInterface
  73. gpg = GnuPGInterface.GnuPG()
  74. gpg.options.meta_interactive = 0
  75. # Add recipients
  76. gpg.options.recipients = options.crypt_to.split(',')
  77. # Open input and output file
  78. encrypted_archive_name = archive_name + '.gpg'
  79. src = open(archive_name, 'rb')
  80. dst = open(encrypted_archive_name, 'wb')
  81. # Run GnuPG
  82. process = gpg.run(['--encrypt'], attach_fhs={'stdin': src, 'stdout': dst})
  83. # Cleanup
  84. process.wait()
  85. dst.close()
  86. src.close()
  87. # Use the encrypted file for the rest of the process
  88. archive_name = encrypted_archive_name
  89. print "Archive encrypted to %s (%.1f MB)" % (archive_name, os.path.getsize(archive_name)/(1024**2))
  90. # Upload to FileDropper if needed
  91. if options.fd_user is not None and options.fd_pass is not None:
  92. import FileDropper
  93. def cb(sent, total):
  94. if total < 0:
  95. print "Upload: %.2f %%" % (100.*float(sent)/float(archive_size))
  96. FileDropper.upload_callback = cb
  97. fd = FileDropper.FileDropper()
  98. fd.login(options.fd_user, options.fd_pass)
  99. # Upload the file
  100. url = fd.upload(archive_name)
  101. # Get the file ID
  102. lst = fd.list()
  103. file_id = -1
  104. for line in lst:
  105. if line[6] == url:
  106. file_id = line[1]
  107. break
  108. if file_id == -1:
  109. # File not found in list!
  110. raise Exception("Error in upload, could not get file ID, permissions not set")
  111. # Set the permissions
  112. fd.set_perm(file_id, FileDropper.FD_PERM_PRIVATE)
  113. # Logout
  114. fd.logout()
  115. print "File uploaded to FileDropper: %s" % url