-import tempfile
from zope.interface import implements
from twisted.application import service, strports
from twisted.internet import defer
from allmydata.interfaces import IDirectoryNode, ExistingChildError, \
NoSuchChildError
from allmydata.immutable.upload import FileHandle
+from allmydata.util.fileutil import EncryptedTemporaryFile
class ReadFile:
implements(ftp.IReadFile)
raise NotImplementedError("Non-streaming producer not supported.")
# we write the data to a temporary file, since Tahoe can't do
# streaming upload yet.
- self.f = tempfile.TemporaryFile()
+ self.f = EncryptedTemporaryFile()
return None
def unregisterProducer(self):
-import os, tempfile, heapq, binascii, traceback, array, stat, struct
+import heapq, traceback, array, stat, struct
from types import NoneType
from stat import S_IFREG, S_IFDIR
from time import time, strftime, localtime
from allmydata.mutable.common import NotWriteableError
from allmydata.immutable.upload import FileHandle
from allmydata.dirnode import update_metadata
-
-from pycryptopp.cipher.aes import AES
+from allmydata.util.fileutil import EncryptedTemporaryFile
noisy = True
use_foolscap_logging = True
return None
-class EncryptedTemporaryFile(PrefixingLogMixin):
- # not implemented: next, readline, readlines, xreadlines, writelines
-
- def __init__(self):
- PrefixingLogMixin.__init__(self, facility="tahoe.sftp")
- self.file = tempfile.TemporaryFile()
- self.key = os.urandom(16) # AES-128
-
- def _crypt(self, offset, data):
- # TODO: use random-access AES (pycryptopp ticket #18)
- offset_big = offset // 16
- offset_small = offset % 16
- iv = binascii.unhexlify("%032x" % offset_big)
- cipher = AES(self.key, iv=iv)
- cipher.process("\x00"*offset_small)
- return cipher.process(data)
-
- def close(self):
- self.file.close()
-
- def flush(self):
- self.file.flush()
-
- def seek(self, offset, whence=0): # 0 = SEEK_SET
- if noisy: self.log(".seek(%r, %r)" % (offset, whence), level=NOISY)
- self.file.seek(offset, whence)
-
- def tell(self):
- offset = self.file.tell()
- if noisy: self.log(".tell() = %r" % (offset,), level=NOISY)
- return offset
-
- def read(self, size=-1):
- if noisy: self.log(".read(%r)" % (size,), level=NOISY)
- index = self.file.tell()
- ciphertext = self.file.read(size)
- plaintext = self._crypt(index, ciphertext)
- return plaintext
-
- def write(self, plaintext):
- if noisy: self.log(".write(<data of length %r>)" % (len(plaintext),), level=NOISY)
- index = self.file.tell()
- ciphertext = self._crypt(index, plaintext)
- self.file.write(ciphertext)
-
- def truncate(self, newsize):
- if noisy: self.log(".truncate(%r)" % (newsize,), level=NOISY)
- self.file.truncate(newsize)
-
-
class OverwriteableFileConsumer(PrefixingLogMixin):
implements(IFinishableConsumer)
"""I act both as a consumer for the download of the original file contents, and as a
Futz with files like a pro.
"""
-import sys, exceptions, os, stat, tempfile, time
+import sys, exceptions, os, stat, tempfile, time, binascii
from twisted.python import log
+from pycryptopp.cipher.aes import AES
+
+
def rename(src, dst, tries=4, basedelay=0.1):
""" Here is a superkludge to workaround the fact that occasionally on
Windows some other process (e.g. an anti-virus scanner, a local search
if self.cleanup and hasattr(self, 'name'):
rm_dir(self.name)
+class EncryptedTemporaryFile:
+ # not implemented: next, readline, readlines, xreadlines, writelines
+
+ def __init__(self):
+ self.file = tempfile.TemporaryFile()
+ self.key = os.urandom(16) # AES-128
+
+ def _crypt(self, offset, data):
+ offset_big = offset // 16
+ offset_small = offset % 16
+ iv = binascii.unhexlify("%032x" % offset_big)
+ cipher = AES(self.key, iv=iv)
+ cipher.process("\x00"*offset_small)
+ return cipher.process(data)
+
+ def close(self):
+ self.file.close()
+
+ def flush(self):
+ self.file.flush()
+
+ def seek(self, offset, whence=0): # 0 = SEEK_SET
+ self.file.seek(offset, whence)
+
+ def tell(self):
+ offset = self.file.tell()
+ return offset
+
+ def read(self, size=-1):
+ index = self.file.tell()
+ ciphertext = self.file.read(size)
+ plaintext = self._crypt(index, ciphertext)
+ return plaintext
+
+ def write(self, plaintext):
+ index = self.file.tell()
+ ciphertext = self._crypt(index, plaintext)
+ self.file.write(ciphertext)
+
+ def truncate(self, newsize):
+ self.file.truncate(newsize)
+
+
def make_dirs(dirname, mode=0777):
"""
An idempotent version of os.makedirs(). If the dir already exists, do