#!/usr/bin/python import ConfigParser import string import sys import os import stat import time import re from ftplib import FTP # # Generate a list of files but exclude certain directories/files based on # exclude_dirs_re and exclude_file_re regular expressions. # def gen_file_list(base_dir, exclude_dirs_re, exclude_files_re): names = os.listdir(base_dir) # Removed files/directories that match exclude patterns for i in range(len(names) - 1, 0, -1): name = names[i - 1] if os.path.isdir(os.path.join(base_dir, name)): if (re.search(exclude_dirs_re, os.path.join(base_dir, name))): names.remove(name) if os.path.isfile(os.path.join(base_dir, name)): if (re.search(exclude_files_re, os.path.join(base_dir, name))): names.remove(name) yield base_dir, names for name in names: if os.path.isdir(os.path.join(base_dir, name)): for (newbase_dir, children) in \ gen_file_list(os.path.join(base_dir, name), \ exclude_dirs_re, exclude_files_re): yield newbase_dir, children # # Connect to an ftp server using provided username/password # def ftp_connect(server, username, password): ftp = FTP(server) ftp.login(username,password) return ftp # # Disconnect from an ftp object # def ftp_disconnect(ftp): ftp.quit() # # Check if a directory exists on the ftp server # def ftp_check_if_dir_exists(ftp, remote_file): # Theory: Save current directory, change directory into any necessary # sub-directory, get directory listing, see if directory exists, # change directory back to original directory. old_pwd = ftp.pwd(); rootdir = os.path.dirname(remote_file) dirname = os.path.basename(remote_file) ftp.cwd(rootdir) dir_listing = [] ftp.retrlines('LIST', dir_listing.append) ret = False for line in dir_listing: words = string.split(line, None, 8) filename_to_compare = string.lstrip(words[-1]) # a directory listing should begin with d if (words[0][0] == 'd'): if (filename_to_compare == dirname): ret = True ftp.cwd(old_pwd) return ret # # Upload a file or create a directory on an ftp server. # def ftp_upload_file(ftp, local_file, remote_file): if os.path.isdir(local_file): if not ftp_check_if_dir_exists(ftp, remote_file): print "creating directory: %s" % remote_file ftp.mkd(remote_file) if os.path.isfile(local_file): # get remote file's modification time remote_mtime = ftp.sendcmd("MDTM " + remote_file) # strip ftp response number do-dad from modificaiton time remote_mtime = remote_mtime.split(' ')[1] # get local file's modifcation time taking into account that the # ftp server's mtime may not be in UTC format. It is added to our # localtime insead for comparison utc_offset = string.atoi(config.get("ftp", "utc_offset")) mtime = time.gmtime(os.stat(local_file).st_mtime) local_mtime = "%4d%2d%2d%2d%2d%2d" % (mtime.tm_year, mtime.tm_mon, mtime.tm_mday, mtime.tm_hour + utc_offset, mtime.tm_min, mtime.tm_sec); local_mtime = local_mtime.replace(' ', '0'); if (local_mtime > remote_mtime): print "uploading %s" % remote_file fd = open(local_file, "rb") ftp.storbinary("STOR " + remote_file, fd) fd.close() # # Function to upload a website to web server via ftp # def ftp_upload_site(): do_upload = raw_input("Would you like to upload your website? (y/n): ") if ((do_upload != 'y') and (do_upload != 'Y')): print "Not uploading site at this time as specified by user" sys.exit(1) server = config.get("ftp", "ftp_server") username = config.get("ftp", "ftp_username") try: password = config.get("ftp", "ftp_password") except: password = raw_input("Please enter your ftp password for %s at %s : " % (username, server)) sys.exit(1) try: exclude_dirs_re = config.get("ftp", "ftp_exclude_dirs") except: exclude_dirs_re = "" try: exclude_files_re = config.get("ftp", "ftp_exclude_files") except: exclude_files_re = "" p = re.compile("(\s)?,(\s)?") exclude_dirs_re = "^" + p.sub("$|^", exclude_dirs_re) + "$" exclude_files_re = "^" + p.sub("$|^", exclude_files_re) + "$" ftp = ftp_connect(server, username, password) for (basepath, children) in gen_file_list(".", exclude_dirs_re, exclude_files_re): for child in children: local_file = os.path.join(basepath, child) remote_file = local_file.lstrip('./') ftp_upload_file(ftp, local_file, remote_file) ftp_disconnect(ftp) # # Main code entry point # # Make sure we have 2 args if len(sys.argv) < 3: print "Error:\n Usage: %s <.conf file> " % sys.argv[0] sys.exit(1) # Get cmdline options conf_file = sys.argv[1] input_dir = sys.argv[2] # Make sure .conf file exists if not os.path.isfile(conf_file): print "Error\n <.conf file> %s does not exist" % conf_file sys.exit(1) # Make sure input directory exists if not os.path.isdir(input_dir): print "Error\n %s does not exist" % input_dir sys.exit(1) config = ConfigParser.ConfigParser() config.read(conf_file) # Use this prefix to match strings in the html file. # For instance, if your configuration file is: # [general] # html_tag_prefix:auto # [header] # html:test # # Then placing will be replaced with # test try: prefix = config.get("general", "html_tag_prefix") except: print "Error: [general]->html_tag_prefix must be "\ "defined in the configuration file." sys.exit(1) sed_opts = "" # Create "full-names" for each section-option pair. These are the strings which # will be replaced in the html files as described above. for section in config.sections(): for option in config.options(section): key_name = "<" + prefix + "_" + section + "_" + option + ">" key_data = config.get(section, option) # delimit newlines and backslashes for sed key_data = "\/".join(key_data.split("/")) key_data = "\\n ".join(key_data.split("\n")) sed_opts += " -e \'s/%s/%s/g\' " % (key_name, key_data) # Use sed to modify all files in the input directory. Note that this is not # recursive at this point for file in os.listdir(input_dir): full_path = os.path.join(input_dir,file) if os.path.isfile(full_path): print "Generating " + file cmd = "sed %s %s > %s" % (sed_opts, full_path, file) os.system(cmd) # # Go ahead and upload the site! # ftp_upload_site()