def write(self, contents, meta, httpmeta=None): """Writes a 411 file with the given plaintext contents, and meta information to the local filesystem. Respects the master file's owner, group, and permission bits. Contents and meta arguments are in the format from get().""" try: # Get standard 411 headers - safe because they were # encrypted. filename = meta["name"] owner = meta["owner"] uid, gid = map(int, owner.split(".")) mode_oct = meta["mode"] except ValueError: raise Error411, "File has malformed 411 headers." try: # This possibly could be done with an OO file class, # but not worth it if we only have two choices. mode = int(mode_oct, 8) if stat.S_ISDIR(mode): mkdir(filename) elif stat.S_ISREG(mode): path, name = os.path.split(filename) mkdir(path) (f, tmp_filename) = tempfile.mkstemp() os.write(f, contents) os.close(f) os.chown(tmp_filename, uid, gid) os.chmod(tmp_filename, stat.S_IMODE(mode)) # mv temp file shutil.move(tmp_filename, filename) else: raise Error411, \ "File %s is an unknown type" % filename # Set file meta data os.chown(filename, uid, gid) os.chmod(filename, stat.S_IMODE(mode)) except (IOError, OSError), msg: raise Error411, \ "Could not write %s: %s" % (filename, msg)
def run(self, filename): """Prepare a 411 file for publishing. Uses a hybrid RSA-Blowfish encryption method.""" # set umask to something sane os.umask(0022) if not filename: raise Error411, "Please specify a file." if self.chroot: filename = os.path.join(self.chroot, filename) if self.doName: # Used by 411 makefile. fullpath = os.path.abspath(filename) if self.chroot: fullpath = fullpath.replace(self.chroot, '') print os.path.join(self.dir411, self.group, self.path411(fullpath)) return if not os.access(filename, os.R_OK): raise Error411, "I cannot find or see '%s'" % filename if not os.access(self.dir411, os.W_OK): raise Error411, "I do not have permission to write to '%s'" % self.dir411 # What kind of file is this? s = os.stat(filename) # File type and permissions in a decimal int. mode = s[stat.ST_MODE] # File type and permission bits in an octal string. mode_oct = oct(mode) # Owner and group id as numeric ints (dont want to rely on # etc/group file). owner = "%d.%d" % (s[stat.ST_UID], s[stat.ST_GID]) # Get the normalized, absolute path name of the file. fullpath = os.path.abspath(filename) if self.chroot: fullpath = fullpath.replace(self.chroot, '') filename411 = self.path411(fullpath) #####MODIFICATIONS TO SUPPORT FILTERING###### # Look for filters in /opt/rocks/var/plugins/411 plugin411_path = '/opt/rocks/var/plugins/411/' sys.path.append(plugin411_path) mod_file = None # Iterate through all the plugins to find the one # that will filter the file. for plugin_file in os.listdir(plugin411_path): if not plugin_file.endswith('.py'): continue mod_name = plugin_file.split('.py')[0] # Import the plugin mod = __import__(mod_name) # Get the filename that the plugin will # process plugin = mod.Plugin() if plugin.get_filename() == fullpath: mod_file = plugin_file break else: plugin = None if mod_file == None: filter = None else: f = open(os.path.join(plugin411_path, mod_file), 'r') filter = f.read() f.close() #####END MODIFICATIONS TO SUPPORT FILTERING###### # 411 file meta data encoded in file. HTTP header style. header = "<?xml version='1.0' standalone='yes'?>\n" header = "<service411>\n" header += "<name>%s</name>\n" % fullpath header += "<mode>%s</mode>\n" % mode_oct header += "<owner>%s</owner>\n" % owner plaintext = header if stat.S_ISREG(mode): file = open(filename, 'r') plaintext += "<content>\n<![CDATA[\n" content = file.read() # Support for pre-send function try: # if the pre_send function exists in the plugin # filter the content through it, before sending # it over f = getattr(plugin, 'pre_send') content = f(content) except AttributeError: pass plaintext += base64.b64encode(content) plaintext += "]]>\n</content>\n" file.close() elif stat.S_ISDIR(mode): plaintext += "<directory>%s</directory>\n" % filename411 else: raise Error411, "I can only publish a regular file or a directory." if filter is not None: plaintext += "<filter>\n<![CDATA[\n" plaintext += base64.b64encode(filter) plaintext += "]]>\n</filter>\n" plaintext += "</service411>" # Call the cryptography engine. msg = self.encrypt(plaintext) # Write the file with the correct name dir411 = self.dir411 if self.group: dir411 = os.path.join(self.dir411, self.group) mkdir(dir411) file = open(os.path.join(dir411, filename411), 'w') file.write(msg) file.close() print "411 Wrote: %s/%s" % (dir411, filename411) print "Size: %s/%s bytes (encrypted/plain)" % \ (len(msg), len(plaintext)) if self.doAlert: self.sendAlert(filename411)
def run(self, filename): """Prepare a 411 file for publishing. Uses a hybrid RSA-Blowfish encryption method.""" if not filename: raise Error411, "Please specify a file." if self.chroot: filename = os.path.join(self.chroot, filename) if self.doName: # Used by 411 makefile. fullpath = os.path.abspath(filename) if self.chroot: fullpath = fullpath.replace(self.chroot, '') print os.path.join(self.dir411, self.group, self.path411(fullpath)) return if not os.access(filename, os.R_OK): raise Error411, "I cannot find or see '%s'" % filename if not os.access(self.dir411, os.W_OK): raise Error411, "I do not have permission to write to '%s'" % self.dir411 # What kind of file is this? s = os.stat(filename) # File type and permissions in a decimal int. mode = s[stat.ST_MODE] # File type and permission bits in an octal string. mode_oct = oct(mode) # Owner and group id as numeric ints (dont want to rely on # etc/group file). owner = "%d.%d" % (s[stat.ST_UID], s[stat.ST_GID]) # Get the normalized, absolute path name of the file. fullpath = os.path.abspath(filename) if self.chroot: fullpath = fullpath.replace(self.chroot, '') filename411 = self.path411(fullpath) #####MODIFICATIONS TO SUPPORT FILTERING###### # Look for filters in /opt/rocks/var/plugins/411 plugin411_path = '/opt/rocks/var/plugins/411/' sys.path.append(plugin411_path) mod_file = None # Iterate through all the plugins to find the one # that will filter the file. for plugin_file in os.listdir(plugin411_path): if not plugin_file.endswith('.py'): continue mod_name = plugin_file.split('.py')[0] # Import the plugin mod = __import__(mod_name) # Get the filename that the plugin will # process plugin = mod.Plugin() if plugin.get_filename() == fullpath: mod_file = plugin_file break else: plugin = None if mod_file == None: filter = None else: f = open(os.path.join(plugin411_path,mod_file), 'r') filter = f.read() f.close() #####END MODIFICATIONS TO SUPPORT FILTERING###### # 411 file meta data encoded in file. HTTP header style. header = "<?xml version='1.0' standalone='yes'?>\n" header = "<service411>\n" header += "<name>%s</name>\n" % fullpath header += "<mode>%s</mode>\n" % mode_oct header += "<owner>%s</owner>\n" % owner plaintext = header if stat.S_ISREG(mode): file = open(filename, 'r') plaintext += "<content>\n<![CDATA[\n" content = file.read() # Support for pre-send function try: # if the pre_send function exists in the plugin # filter the content through it, before sending # it over f = getattr(plugin, 'pre_send') content = f(content) except AttributeError: pass plaintext += base64.b64encode(content) plaintext += "]]>\n</content>\n" file.close() elif stat.S_ISDIR(mode): plaintext += "<directory>%s</directory>\n" % filename411 else: raise Error411, "I can only publish a regular file or a directory." if filter is not None: plaintext += "<filter>\n<![CDATA[\n" plaintext += base64.b64encode(filter) plaintext += "]]>\n</filter>\n" plaintext += "</service411>" # Call the cryptography engine. msg = self.encrypt(plaintext) # Write the file with the correct name dir411 = self.dir411 if self.group: dir411 = os.path.join(self.dir411, self.group) mkdir(dir411) file = open(os.path.join(dir411, filename411), 'w') file.write(msg) file.close() print "411 Wrote: %s/%s" % (dir411, filename411) print "Size: %s/%s bytes (encrypted/plain)" % \ (len(msg), len(plaintext)) if self.doAlert: self.sendAlert(filename411)