# Photo Photograph / Video Portal Generator
# (c) 2000-2011 Sandipan Gangopadhyay
strCodeVersion = "53.0"
# ========================================================================== WEBSITE PUBLISHER =====================================================================
# Next: XML processing for YouTube, titles, inserts, using namespaces, Password protected pages, process images to allow native to be opened on click, integration of story-writer version and auto-propagation scripts, fix emailer, RSS viewer portlet, emailer for pictures
# Next: New slideshow
# Next: Remove PIL from emailers
# Next: Integrate album with Android App
# Version 53.0 of September 24, 2011 - Banner Changes through slideshow
# Version 52.0 of July 08, 2011 - Google Translate on the footer
# Version 51.0 of March 20, 2011 - Breadcrumbs have backgrounds
# Version 51.0 of March 20, 2011 - Page Contents (Titles), emailer
# Version 50.0 of March 12, 2011 - Jump to page top from each section header and a section at the bottom with a list of child pages
# Version 49.0 of March 05, 2011 - Navigation buttons beside the bread crumbs, Site Map now refers to bread crumbs as page hierarchy, Definable page background images or color, CSS3 stretching for background images
# Version 48.0 of February 26, 2011 - Site Map to also list bread crumbs (for a sense of the hierarchy)
# Version 47.0 of February 23, 2011 - Do not put when content lines end with '>', meaning that when the content is HTML
# Version 46.0 of February 20, 2011 - Current Page's Menu item's "under-bar" starts RED once the new page loads
# Version 45.0 of February 16, 2011 - Auto scroller and Private folders (for password protect, etc.)
# Version 40.0 - 44.0 of January 12, 2011 - Look and feel: Blue lines look, relative links to banners and icons, fixed a ton of HTML4.01 and CSS bugs, floating reading panel
# Version 40.0 of January 12, 2011 - Look and feel: Side panels
# Version 39.0 of January 09, 2011 - Consumes Auto Generated content such as SandhirImagePublisherV27
# Version 38.0 of December 05, 2010 - HTML and CSS bugs fixed at Home Page Level
# Version 37.0 of December 05, 2010 - Integrated Google Search
# Version 36.0 of November 28, 2010 - Changes the banner image onclick and a fix for the bug on EmailTheWeb integration (was sending out the parent page)
# Version 35.0 of November 28, 2010 - removed Album publisher code
# Version 34.0 of November 27, 2010 - Site Publisher - All works, but HTML bugs remaining ... some of them need style refs and some are simply not bugs
# Versions all the way up to ...
# Version 26.0 of November 21, 2010 - Site Publisher
# ========================================================================== ALBUM PUBLISHER =====================================================================
# Version 24.0 of July 03, 2009 - Folder SCP AND Twitter Interface
# Version 23.0 of May 22, 2009 - Facebook Share Partner Preview meta-data in thumbnail pages, inclusion of special YouTube account credentials in ALT text, integration with FB (through a share link!) and starting on Auto-SCP to the web server
# Version 22.0 of April 30, 2009 - YouTube integration for Videos through Google Data API
# Version 21.0 of January 18, 2009 - Corel Painter writes JPG, not PNG ... so we put in a converter for these. The JPG becomes a native file; Shuts off extra stuff by default
# Version 20.0 of January 13, 2009 - Reads key super album related info (local and web paths) from a config file so that the same prog can be used for all albums; Common eMailer;
# Version 19.0 of January 10, 2009 - Can publish pictorial stories
# Version 18.0 of December 25, 2008 - Representative photo from the album is shown with the album name in the Album List page
# Version 17.0 of May 11, 2008 - Album names are split up so that they are more reader friendly AND more search-engine friendly (Longwood Gardens Visit instead of LongwoodGardensVisit)
# Version 16.1 of May 1, 2008 - Disabled Image.Keys because for Canon Cameras, EXIF values were binary and causing client side JS to fail (unterminated string literals)
# Version 16.0 of September 4, 2007 - On WinVistaUlti on Node18, on Python-2.5.1, had to fix spl char on Sandhir
# Version 15.0 of December 11, 2006 - TouchMode ... longstanding need to not reprocess existing folders
# Version 10.0 of May 23, 2006 - Working on including GIF animated version of video thumbnails for .AVI and .MPEG
# Version 9.0 of April 18 - May 15, 2006 - Handling Videos in thumbnail page AND emailing out photographs/videos
# Version 8.0 of January 2, 2006 - Touch-file concept for folders already processed
# Version 7.2 of April 23, 2005 - Multi-depth folder bugfixes
# Version 7.1 of October 8, 2004 - Album title and caption on Thumbnails Page
# Version 7.0 of October 8, 2004 - Thumbnails Page (The C8080 came in today) completed in a day!
# Version 6.0 of June 17, 2004 - Reverse sort order version
# Version 5.0 of August 03, 2003 - Top level slide show version - has not been implemented
# Version 4.0 of May 26 - June 07, 2003 - Slide show version
# Version 3.0 of May 26, 2003 requires ExifTags Utility to read JPEG file properties
# Version 2.0 of May 25, 2003 requires Python Image Library Version 1.1.4 for Python Version 2.2
# Version 1.0 on Python Version 2.2
# Based on Reporter Version 3.8 of 2002 (dates of modification, etc added)
# Version broken off for the Galaxy Svc Portal Version 3.7.2 of 2002.04.08
# Previous Version 3.7 of 2000.03.22
# MODULE IMPORT
import time, os, Image, urllib, string, math, os.path, calendar, gdata.youtube, gdata.youtube.service, sys, rfc822
import xml.etree.ElementTree as ET
# GLOBAL VARIABLE DECLARATION
strPortalPage = "Page.html" # Name of the List Page that lists all albums
strConfigFile = "configuration.txt" # Name of the file, which if present will be read and values used to override some of the global declarations here
lstConfigTypes = ["strReport1Path", "strReport3Path", "strAlbumPath", "strWebsitePath", "binStory", "binTouchMode", "binEmbedVideo", "intLogLevel", "binYouTube", "binYTPrivate", "strYTDeveloperKey", "strYTClientId", "strYTEmail", "strYTPwd", "strYTSource"]
strThumbsPage = "thumbs.html" # Name of the Thumbnail Page for each album
strDescriptionFileName = "111-FileDescription.txt" # File in which description of the image/video can be stored. If present, it will be added to the caption for that image to be brought up along with JFIF info
strAlbumIconFileName = "111-AlbumIcon.txt" # File in which the file name of the image is stored that will represent the album in the album list page. In its absence, the first image in the album will be selected
strFolderProcessedMarker = "x-FolderProcessed.txt" # Flag that the folder has been processed - Deprecated?
strVideoProcessingFolder = "VideoExtraction" # Folder where all the working files for video extraction are temporarily stored
strReport1Path = "Images" # Folder in the album where all the assets are
strReport2Path = "Videos" # Folder in the album where all the assets are - Not used; Images hold both images and videos
strReport3Path = "OccasionallyImmortal" # Folder in the album where all the assets are
# strAlbumPath = "E:\\Data\\Reporter\\reporter" # Where on the computer where this program is being run is this album - Windows FS - the Prog will first chdir to it
strAlbumPath = "E:\\Data\\Reporter\\reporter\\PriorVersions\\CodeBackups\\reporterV220"
# strWebsitePath = "/family/doc-rep/certificates2" # Where in the website is going to be this album or story - Unix FS - We need to send this to the Emailer ... we need to make this change in the future
# strWebsitePath = "/family/albumer2" # Where in the website is going to be this album or story
# strWebsitePath = "/family/albumer3" # Where in the website is going to be this album or story
strWebsitePath = "/links/stories/immortal/reporterV190" # Where in the website is going to be this album or story
strSmallDir = "Smalls" # Folder in each album where small version of images are stored
strThumbsDir = "Thumbnails" # Folder in each album where thumbnail version of images are stored
strTemplatePath = "report-templates/" # Folder in the super album where web-page templates are stored
strTempFile = "xxx.txt" # Used for temporarily storing information about images and videos
lstStyleFiles = ["album.html", "dashstyle.css", "image2.jpg", "xmp1.jpg"] # Contents of Style Folder in each album
strThumbBkgrd = "./style/crinklepaper.jpg" # Where the background for thumbnails for List Page is stored
strEmailIcon = "../../../Icons/email018.gif" # Icon for Email button used to pop up form page to send images by email
strThumbFileExt = ".jpg" # Default thumbnail type ... videos use .gif for the animated icons
strReadError = "---ERROR---" # Value when a file reading has resulted in an error
binEmbedVideo = 0 # Indicates whether we embed video in the thumbnail page or embed the animated gif version (video is NOT advised ... large vids will take a long time for the album page to load)
binTouchMode = 1 # Starts V15.0 - Whether folders without touchfiles should not be processed - saves a TON of time ... the List Page is regenrated and also each album page, but the images, videos are not even opened
strTouchFile = strThumbsPage # Only if this file exists in the album folder when the binTouchMode is true, the folder is fully processed ... currently set to the Thumbnail Page
binYouTube = 1 # binYouTube when true will result in the video files with a corresponding .ytb file being uploaded to youtube if possible
binYouTubePrivate = 1 # If true, will result in the video being uploaded into the private area in YouTube
strYouTubeCredsFile = "YouTubeCreds.txt" # File with YouTube credentials
strYouTubeMarkerFileExt = "ytb" # File extension for file that signifies that the video should be uploaded to YouTube and later, contains YouTube upload data
# INITIALIZE LOG LEVEL
intLogLevel = 5
# RECURSION HANDLERS AND GENERAL GLOBAL VARIABLE / ITERATOR INITIALIZATION (We have minimized these to ensure the program can be broken up into classes later and reduce cohesion)
lstOuterFolderItems = [] # Do not remember
intFolderDepth = 0 # Depth of recursion into nested album folders
strSection = "" # The section of the List Page being built recursively
lstAlbums = [] # List of albums within the Super Album
intTotalItems = 0 # Total number of digital assets hosted
# GLOBAL SETTINGS
intImageWidth = 600 # Width in pixels for the width of an image. Used where?
intImageHeight = 500 # Height in pixels for the width of an image. Used where?
intSmallWidth = 640 # Width in pixels for the width of the small version of an image
intSmallHeight = 480 # Height in pixels for the width of the small version of an image
intThumbWidth = 240 # Width in pixels for the width of the thumbnail version of an image
intThumbHeight = 180 # Height in pixels for the width of the thumbnail version of an image
intThumbsWidthwise = 5 # The number of thumbnails across the width of a page
intExtractsPerVideo = 5 # The number of frames extracted from a video file for stitching together in the Thumbnail GIF
intIntervalsInExtracts = 100 # mSeconds # Interval between frames (not really used?)
intExtracts2PerVideo = 30 # The number of frames extracted from a video file for stitching together in the Small / Snaps GIF
intIntervalsInExtracts2 = 20 # mSeconds # Interval between frames (not really used?)
# STORY PUBLISHER VARIABLE DECLARATION
binStory = 0 # True indicates that the program should process a pictorial story, not an album - The Story Switch
intThumbShadowOffset = 5 # The depth of shadow for the thumbnails and narrative panels
strResearchDir = "Data" # Folder in which data, items, sketches, etc about the story plates are stored
strPlateImageTypeExt = "png" # We are using PNGs for story images as we are concerned about IPR liabilities associated with JPGs and GIFs
strNativeExt = "eps" # Extension / type of the actual native artwork file ... EPS or SVG ... vector graphics supported by InkScape, Adobe Illustrator, Corel Painter
strPlatePrefix = "plate" # Each story picture starts with this prefix
# Icon Files
strSmllIcon = "../../Icons/Picture.png" # Link to the small Version of the PNG - Painting
strLargIcon = "../../Icons/Picture.png" # Link to the native, large Version of the PNG - Painting
strNatvIcon = "../../Icons/gear.gif" # Link to the native Version of the file - Gears
strItemIcon = "../../Icons/search.png" # Link to research files and items (photographs, docs) - Magnifying Glass
strLinkIcon = "../../Icons/link.png" # Link to links - Chain
strIdeaIcon = "../../Icons/bulb.png" # Link to thoughts, discussions and ideas - A light bulb
lstNarrativePrefixes = ["Narrative: ", "Dialogue: ", "Item: ", "Link: ", "Discussion: "]
# Prefixes in Narrative Files
lstNativeGraphicsExt = ["ai", "svg", "rif", "eps", "jpg"]
# Covers Adobe Illustrator, Inkscape, Corel Painter, Encapsulated PostScript
# YOUTUBE UPLOAD DECLARATIONS
binYouTube = 1 # binYoutube when true will upload all videos unless each video's .ytb file has "DONT UPLOAD" in it to YouTube
binYTPrivate = 1 # binYTPrivate when true will upload as a Private video (Dhirja's wish)
strYTDeveloperKey = 'XXX' # YouTube Developer Credentials ... Not published here, of course!
strYTClientId = 'XXX' # ID of the client (this app)
strYTEmail = 'XXX' # User ID of the account
strYTPwd = 'XXX' # Pwd of the account
strYTSource = 'Sandipans Album Publisher' # Identification of the Application doing the upload (this app)
strYTVideoID = 'xxx' # Blank YouTube Video ID
strYTBFileExt = '.ytb' # YouTube Information File Extension (Created for each video that is uploaded)
strYTBFolderFlagFileName = "dontupload.ytb" # If a folder has a file of this name in it, videos in the folder are NOT uploaded to YouTube
# UTILITY TO WRITE A STRING TO THE ALBUM LIST PAGE
def fnWrite(strWrite):
return
try:
flWriter = open(strPortalPage, "a")
flWriter.write(strWrite)
flWriter.close()
except:
print "Oops! Could not write %s" % strWrite
pass
return
# UTILITY TO WRITE A STRING TO A FILE
def fnFileWrite(strFile, strWrite, chrMode):
try:
flWriter = open(strFile, chrMode)
flWriter.write(strWrite)
flWriter.close()
except:
print "Oops! Could not write to file [%s]: %s" % (strFile, strWrite)
pass
return
def fnFileWriteRaw(strFile, strWrite, chrMode):
flWriter = open(strFile, chrMode)
flWriter.write(strWrite)
flWriter.close()
return
# UTILITY TO READ A FILE INTO A STRING
def fnRead(strRead):
try:
flReader = open(strRead, "r")
strReader = flReader.read()
flReader.close()
except:
# print "Oops! Could not read %s" % strRead
strReader = strReadError
return strReader
# UTILITY TO READ A FILE INTO A LIST OF LINES
def fnReadLines(strRead):
try:
flReader = open(strRead, "r")
lstReader = flReader.readlines()
flReader.close()
except:
# print "Oops! Could not read %s" % strRead
lstReader = [strReadError]
return lstReader
def fnCleanReadLines(strRead):
try:
flReader = open(strRead, "r")
lstReader = flReader.readlines()
flReader.close()
lstCleanReader = []
for strRead in lstReader:
lstCleanReader.append(string.rstrip(strRead, "\n"))
except:
# print "Oops! Could not read %s" % strRead
lstReader = [strReadError]
return lstCleanReader
# SPLITS YYYYMMDD-ThisIsTheNameOfTheAlbum to MM DD, YYYY - This Is The Name Of The Album FOR ALBUM OR STORY NAMES
def fnSplitFileName(strFolderName):
strSplitName = ""
strSplit1 = "Year"
strSplit2 = "0"
strSplit3 = "Year"
strSplit4 = ""
strSplit5 = ""
lstSplit1 = string.split(strFolderName,'-')
if len(lstSplit1) == 1:
lstSplit1.append(lstSplit1[0])
lstSplit1[0] = time.strftime("%Y%m%d")
if len(lstSplit1[0]) > 3:
strSplit1 = lstSplit1[0][0:4]
if len(lstSplit1[0]) > 5:
strSplit2 = lstSplit1[0][4:6]
if len(lstSplit1[0]) > 7:
strSplit3 = lstSplit1[0][6:8]
intCtr1 = 0
for strSpliter1 in lstSplit1:
if intCtr1 > 0:
strSplit4 = strSplit4 + strSpliter1
intCtr1 = intCtr1 + 1
intCtr2 = 0
for chrChar in strSplit4:
if ((chrChar.isupper())):
if ((intCtr2 > 0) and ((strSplit4[intCtr2 - 1].isupper()))):
strSplit5 = strSplit5 + " " + chrChar
else:
strSplit5 = strSplit5 + " " + chrChar
elif ((chrChar.isdigit())):
if ((intCtr2 > 0) and ((strSplit4[intCtr2 - 1].isdigit()))):
strSplit5 = strSplit5 + chrChar
else:
strSplit5 = strSplit5 + " " + chrChar
else:
strSplit5 = strSplit5 + chrChar
intCtr2 = intCtr2 + 1
strSplitName = calendar.month_name[int(strSplit2)] + " " + strSplit3+ ", " + strSplit1 + " - " + strSplit5
return strSplitName
def fnConvertDate(strDate):
strDate = strDate + "-Hello"
strConvert = fnSplitFileName(strDate)
strThisDate = string.split(strConvert, "-")[0]
return strThisDate
# PRIMARILY USED FOR DEBUGGING
def fnPause():
strInput = raw_input("Hit enter key to continue")
return 1
# READS THE CONFIG FILE FOR THE PROGRAM
def fnReadConfig():
global strReport1Path, strReport3Path, strAlbumPath, strWebsitePath, binStory, binTouchMode, binEmbedVideo, intLogLevel, intThumbWidth, intThumbHeight, intThumbsWidthwise, strEmailIcon, binYouTube
global binYTPrivate, strYTDeveloperKey, strYTClientId, strYTEmail, strYTPwd, strYTSource
# Load the list of lines from the text file
lstConfig = fnReadLines(strConfigFile)
# Create individual lists of Narratives, dialogue, etc
for strConfigLine in lstConfig:
# For each line, check if it is one of the types of narratives
intPrefixNumber = 0
for strConfigType in lstConfigTypes:
# If it matches
intPrefixNumber = intPrefixNumber + 1
if strConfigLine[0:len(strConfigType)] == strConfigType:
# Strip the line off its preceding prefix and the succeeding newline character
strConfigInLine = strConfigLine[len(strConfigType):].strip()
# Numbers are from this list declared above - lstConfigTypes = ["strReport1Path", "strReport3Path", "strAlbumPath", "strWebsitePath", "binStory", "binTouchMode", "binEmbedVideo", "intLogLevel", "binYouTube", "binYTPrivate", "strYTDeveloperKey", "strYTClientId", "strYTEmail", "strYTPwd", "strYTSource"]
# Append to the appropriate list
if intPrefixNumber == 1:
strReport1Path = strConfigInLine.strip()
elif intPrefixNumber == 2:
strReport3Path = strConfigInLine.strip()
elif intPrefixNumber == 3:
strAlbumPath = strConfigInLine.strip()
elif intPrefixNumber == 4:
strWebsitePath = strConfigInLine.strip()
elif intPrefixNumber == 5:
binStory = string.atoi(strConfigInLine.strip())
elif intPrefixNumber == 6:
binTouchMode = string.atoi(strConfigInLine.strip())
elif intPrefixNumber == 7:
binEmbedVideo = string.atoi(strConfigInLine.strip())
elif intPrefixNumber == 8:
intLogLevel = string.atoi(strConfigInLine.strip())
elif intPrefixNumber == 9:
binYouTube = string.atoi(strConfigInLine.strip())
elif intPrefixNumber == 10:
binYTPrivate = string.atoi(strConfigInLine.strip())
elif intPrefixNumber == 11:
strYTDeveloperKey = strConfigInLine.strip()
elif intPrefixNumber == 12:
strYTClientId = strConfigInLine.strip()
elif intPrefixNumber == 13:
strYTEmail = strConfigInLine.strip()
elif intPrefixNumber == 14:
strYTPwd = strConfigInLine.strip()
elif intPrefixNumber == 15:
strYTSource = strConfigInLine.strip()
else:
# Ignore any other kinds of lines ... we wouldn't know what to do with them
pass
if binStory:
# Thumbnails will be the actual pictures in the story, so bigger
intThumbWidth = 400 # The thumbnails in a story Album Page are the actual plates of the pictorial story ... we want them larger
intThumbHeight = 300
intThumbsWidthwise = 3 # Fewer thumbnails across the Album Page since they are larger
strEmailIcon = "../../Icons/email018.gif" # The location of the email image is different for the story albums, it has less depth than photo albums ... we need to fix all this
if intLogLevel > 0:
print """
Loaded Config:
--------------
strReport1Path: [%s],
strReport3Path: [%s],
strAlbumPath: [%s],
strWebsitePath: [%s],
binStory: [%s],
binTouchMode: [%s],
binEmbedVideo: [%s],
intLogLevel: [%s],
binYouTube: [%s],
binYTPrivate: [%s],
strYTDeveloperKey: [%s],
strYTClientId: [%s],
strYTEmail: [%s],
strYTPwd: [%s],
strYTSource: [%s]
""" % (strReport1Path, strReport3Path, strAlbumPath, strWebsitePath, binStory, binTouchMode, binEmbedVideo, intLogLevel, binYouTube, binYTPrivate, strYTDeveloperKey, strYTClientId, strYTEmail, strYTPwd, strYTSource)
return 0
# PRINTS LOGS AT VARIOUS LEVELS OF SEVERITY
def fnLog(intSeverity, strMessage):
intNowLogLevel = intLogLevel
if intSeverity < len(lstErrorLevels):
strSeverity = lstErrorLevels[intSeverity]
else:
strSeverity = "Level: %02d" % intSeverity
if intSeverity <= intNowLogLevel:
print ">>>> LOG at SEVERITY LEVEL [%s] = [%s]" % (strSeverity, strMessage)
# SPLITS NNN-ThisIsTheNameOfThePageFolder to [NNN, This Is The Name Of The Album]
def fnFolderTitle(strFolderName):
strSplitName = ""
strSplit1 = "Year"
strSplit2 = "0"
strSplit3 = "Year"
strSplit4 = ""
strSplit5 = ""
lstSplit1 = string.split(strFolderName,'-')
if len(lstSplit1) == 1:
lstSplit1.append(lstSplit1[0])
lstSplit1[0] = time.strftime("%Y%m%d")
if len(lstSplit1[0]) > 3:
strSplit1 = lstSplit1[0][0:4]
if len(lstSplit1[0]) > 5:
strSplit2 = lstSplit1[0][4:6]
if len(lstSplit1[0]) > 7:
strSplit3 = lstSplit1[0][6:8]
intCtr1 = 0
for strSpliter1 in lstSplit1:
if intCtr1 > 0:
strSplit4 = strSplit4 + strSpliter1
intCtr1 = intCtr1 + 1
intCtr2 = 0
for chrChar in strSplit4:
if ((chrChar.isupper())):
# FOR RUNNING CAPS
if ((intCtr2 > 0) and ((strSplit4[intCtr2 - 1].isupper()))):
strSplit5 = strSplit5 + " " + chrChar
# IF THE FIRST CHAR IS A CAP
elif (intCtr2 == 0):
strSplit5 = strSplit5 + "" + chrChar
# FOR ALL OTHER CAPS, CHANGE THE WORD
else:
strSplit5 = strSplit5 + " " + chrChar
# IF A DIGIT
elif ((chrChar.isdigit())):
# IF RUNNING DIGITS
if ((intCtr2 > 0) and ((strSplit4[intCtr2 - 1].isdigit()))):
strSplit5 = strSplit5 + chrChar
# IF NOT RUNNING DIGITS, CHANGE THE WORD
else:
strSplit5 = strSplit5 + " " + chrChar
else:
strSplit5 = strSplit5 + chrChar
intCtr2 = intCtr2 + 1
strSplitName = calendar.month_name[int(strSplit2)] + " " + strSplit3+ ", " + strSplit1 + " - " + strSplit5
return lstSplit1[0], strSplit5
# RUNS A PASS THROUGH THE SITE STRUCTURE BUILDING THE SITE MAP INCLUDING A LINKED LIST THAT WILL BE USED FOR BREADCRUMBS AND HIERARCHICAL MENUS
def fnAnalyzeFolder(strFolderPath, strFolderName, intPageSerial):
try:
# LOCATE ALL FILES AND FOLDERS IN THIS FOLDER
lstFolderContents = os.listdir(strRootPath + "/" + strFolderPath + "/" + strFolderName)
fnLog(5, "Content of Folder: [%s/%s]: %s" % (strFolderPath, strFolderName, lstFolderContents))
fnLog(6, "Resolution of Path: PC [%s] and Web Server [/%s]" % (strRootPath + "/" + strFolderPath + "/" + strFolderName, strFolderPath + "/" + strFolderName))
# THE HOME PAGE IS ALREADY ANALYZED. FOR OTHERS ...
if intPageSerial > 0:
# FIND OUT IMPORTANT DETAILS TO LOAD INTO THE SITE MAP
# Page Title
try:
if binFolderNameIsTitle:
# TITLE IS CONSTRUCTED FROM THE FOLDER NAME ...
strThisPageTitle = fnFolderTitle(strFolderName)[1]
else:
if lstMetaFiles[4] in lstFolderContents:
fnLog(6, "Title: %s" % fnReadLines(strRootPath + "/" + strFolderPath + "/" + strFolderName + "/" + lstMetaFiles[4]))
# TITLE IS EXPLICITLY RECORDED IN THE TITLE FILE
strThisPageTitle = fnReadLines(strRootPath + "/" + strFolderPath + "/" + strFolderName + "/" + lstMetaFiles[4])[0]
else:
strThisPageTitle = strDefaultMetaTitle
except:
strThisPageTitle = strDefaultMetaTitle
fnLog(6, strThisPageTitle)
# Page SubTitle
if lstMetaFiles[5] in lstFolderContents:
fnLog(6, "SubTitle: %s" % fnReadLines(strRootPath + "/" + strFolderPath + "\\" + strFolderName + "\\" + lstMetaFiles[5]))
strThisPageSubTitle = fnReadLines(strRootPath + "/" + strFolderPath + "\\" + strFolderName + "\\" + lstMetaFiles[5])[0]
else:
strThisPageSubTitle = strDefaultMetaSubTitle
# Page Author
if lstMetaFiles[3] in lstFolderContents:
fnLog(6, "Author: %s" % fnReadLines(strRootPath + "/" + strFolderPath + "\\" + strFolderName + "\\" + lstMetaFiles[3]))
strThisPageAuthor = fnReadLines(strRootPath + "/" + strFolderPath + "\\" + strFolderName + "\\" + lstMetaFiles[3])[0]
else:
strThisPageAuthor = strDefaultMetaAuthor
# UPDATE THE SITE MAP
arrLstSiteMap.append([intPageSerial, strThisPageTitle, strThisPageSubTitle, strThisPageAuthor, strFolderName, strFolderPath, lstParentPageSerialStack[len(lstParentPageSerialStack)-1], len(lstParentPageSerialStack)])
fnLog(5, "Sita Map Array = %s" % arrLstSiteMap)
# NOTE DOWN PAGE SERIAL NUMBER IN ITS FOLDER
try:
os.remove(strRootPath + "/" + strFolderPath + "/" + strFolderName + "/" + lstMetaFiles[12])
except:
print "Couldn't erase"
pass
fnFileWrite(strRootPath + "/" + strFolderPath + "/" + strFolderName + "/" + lstMetaFiles[12], "%d\n" % intPageSerial, "a")
if binFolderNameIsTitle:
try:
fnFileWrite(strRootPath + "/" + strFolderPath + "/" + strFolderName + "/" + lstMetaFiles[4], "%s" % fnFolderTitle(strFolderName), "w")
except:
pass
# LOOK FOR SUB FOLDERS NOW
# PUSH THE PARENT FOLDER SERIAL INTO STACK
lstParentPageSerialStack.append(intPageSerial)
fnLog(6, "Parent Stack = %s" % lstParentPageSerialStack)
if strMetaAutoContentFileName in lstFolderContents:
# THIS IS AN AUTOGENERATED FOLDER - DO NOT RECURSE FURTHER - STOP RIGHT HERE
pass
else:
for strFolderContent in lstFolderContents:
try:
os.listdir(strRootPath + "/" + strFolderPath + "/" + strFolderName + "/" + strFolderContent)
# IF NOT PROTECTED FOLDER, RECURSE
if strFolderContent in lstProtectedFolders:
pass
else:
# INCREMENT THE PAGE SERIAL COUNTER
intPageSerial = intPageSerial + 1
# IF IT GETS HERE IT IS A FOLDER
fnLog(2, "Processing Folder #%d: [%s | %s | %s]" % (intPageSerial, strFolderPath, strFolderName, strFolderContent))
# RECURSE TO PROCESS CHILDREN
intPageSerial = fnAnalyzeFolder(strFolderPath + "/" + strFolderName, strFolderContent, intPageSerial)
except:
# NOT A FOLDER - DON'T BOTHER
pass
# POP THE FOLDER SERIAL FROM THE STACK
lstParentPageSerialStack.pop()
except:
fnLog(1, "Pass 1 Folder Analysis failed on [%s] because of [%s]" % (strFolderName, sys.exc_info()[0]))
return intPageSerial
# FINDS BANNER IMAGES IN SPECIFIED FOLDER AND CONSTRUCTS A CLIENT SIDE JAVASCRIPT STRING WITH THE NAMES
# THE PAGES SELECT A BANNER BASED ON TIME AND LOAD THEM DYNAMICALLY
# THE FIRST IMAGE WILL BE THE DEFAULT THAT WILL STAY ON THE PAGE IF THE CLIENT SIDE JS LOAD FAILS - SO IT SHOULD BE A GOOD ONE
# CLIENT SIDE JS LOAD LOGIC HAS BEEN TESTED TO WORK ON IE AND BLACKBERRY BROWSERS!
def fnListBannersFound(strFolderPath):
lstFiles = os.listdir(strFolderPath)
lstBannerFiles = []
strBannerFiles = ""
for strFileName in lstFiles:
lstNamePieces = string.split(strFileName, ".")
if lstNamePieces[1] == "jpg":
if len(lstBannerFiles) == 0:
strBannerFiles = "\"" + strFileName + "\""
else:
strBannerFiles = strBannerFiles + ", \"" + strFileName + "\""
lstBannerFiles.append(lstNamePieces[0])
fnLog(6, "Banners found = [%s]" % strBannerFiles)
return lstBannerFiles, strBannerFiles
# GIVEN THE PAGE SERIAL NUMBER, THIS WILL FIND TITLE, SUBTITLE, AUTHOR, PARENT SERIAL, PAGE DEPTH INFO LOADED INTO THE SITE MAP IN ANALYSIS (FIRST) PASS
def fnFindEntryInSiteMap(intPageSerial):
for lstPageDetails in arrLstSiteMap:
if int(lstPageDetails[0]) == int(intPageSerial):
fnLog(5, lstPageDetails)
return lstPageDetails
fnLog(2, "Serial number [%s] not found." % intPageSerial)
return []
# CONSTRUCTS AN HTML STRING CONTAINING THE BREADCRUMBS FOR THE GIVEN PAGE
def fnBreadCrumbs(strBreadCrumbs, intPageSerial, intOriginalFolderDepth, binNavButtons):
lstPageEntry = fnFindEntryInSiteMap(intPageSerial)
intPageParent = int(lstPageEntry[6])
intPageDepth = int(lstPageEntry[7])
strFolder = lstPageEntry[4]
strPath = lstPageEntry[5]
strComments = lstPageEntry[2]
strName = lstPageEntry[1]
strNavigator = ""
strPathToHomeFolder = ""
for intDepthCtr in range(0, intOriginalFolderDepth-1):
strPathToHomeFolder = strPathToHomeFolder + "../"
if strBreadCrumbs == "":
strNavigator = fnNavigator(intPageSerial)
if binNavButtons:
strBreadCrumbs = "%s
" + strBreadCrumbs
return strBreadCrumbs
# FIND PARENT AND ADJACENT SIBLINGS OF PAGE FOR NAVIGATION BUTTONS - ASSUMES SITE-MAP-ARRAY IS SORTED FOR ADJACENCY OF SIBLINGS
def fnNavigator(intPageSerial):
strNavigator = "%03d" % intPageSerial
lstPageEntry = fnFindEntryInSiteMap(intPageSerial)
intPageDepth = int(lstPageEntry[7])
strFolder = lstPageEntry[4]
strPath = lstPageEntry[5]
strComments = lstPageEntry[2]
strName = lstPageEntry[1]
intOriginalFolderDepth = intPageDepth
strNavigator = ""
strPathToHomeFolder = ""
for intDepthCtr in range(0, intOriginalFolderDepth-1):
strPathToHomeFolder = strPathToHomeFolder + "../"
# FIND OUT ABOUT THE PAGE
lstPageEntry = fnFindEntryInSiteMap(intPageSerial)
# FIND OUT ABOUT THE PARENT
intPageParent = int(lstPageEntry[6])
if intPageParent < 0:
# THIS IS THE HOME PAGE - NO PARENT
strParentNav = " " % (strPathToHomeFolder, "X", "X")
else:
lstParentEntry = fnFindEntryInSiteMap(intPageParent)
strParentFolder = lstParentEntry[4]
strParentPath = lstParentEntry[5]
strParentComments = lstParentEntry[2]
strParentName = lstParentEntry[1]
strParentNav = " " % (strPathToHomeFolder, strParentPath + "/" + strParentFolder, strPageFileName, strParentName, strPathToHomeFolder, strParentName, strParentName)
# FIND OUT ABOUT ANY PRECEDING SIBLING
intPrecedingSiblingSerial = -1
if intPageSerial > 2: # THERE IS NO WAY #1 COULD HAVE A PRECEDING SIBLING, AS IT IS THE FIRST PAGE UNDER #0, THE HOME PAGE
for intMaybePS in range(intPageSerial-1, 0, -1):
lstPrecedingSiblingEntry = fnFindEntryInSiteMap(intMaybePS)
intPrecedingSiblingParent = int(lstPrecedingSiblingEntry[6])
strPrecedingSiblingFolder = lstPrecedingSiblingEntry[4]
strPrecedingSiblingPath = lstPrecedingSiblingEntry[5]
strPrecedingSiblingComments = lstPrecedingSiblingEntry[2]
strPrecedingSiblingName = lstPrecedingSiblingEntry[1]
if intPrecedingSiblingParent == intPageParent:
# THEY HAVE A COMMON PARENT - THEY SEEM TO BE TRUE SIBLINGS!
intPrecedingSiblingSerial = intMaybePS
break
if intPrecedingSiblingSerial > 0:
strPrecedingSiblingNav = "" % (strPathToHomeFolder, strPrecedingSiblingPath + "/" + strPrecedingSiblingFolder, strPageFileName, strPrecedingSiblingName, strPathToHomeFolder, strPrecedingSiblingName, strPrecedingSiblingName)
else:
strPrecedingSiblingNav = " " % (strPathToHomeFolder, "X", "X")
# FIND OUT ABOUT ANY SUCCEEDING SIBLING
intSucceedingSiblingSerial = -1
if intPageSerial < intNumberOfPages: # THERE IS NO WAY #1 COULD HAVE A PRECEDING SIBLING, AS IT IS THE FIRST PAGE UNDER #0, THE HOME PAGE
for intMaybeSS in range(intPageSerial+1, intNumberOfPages+1, 1):
lstSucceedingSiblingEntry = fnFindEntryInSiteMap(intMaybeSS)
intSucceedingSiblingParent = int(lstSucceedingSiblingEntry[6])
strSucceedingSiblingFolder = lstSucceedingSiblingEntry[4]
strSucceedingSiblingPath = lstSucceedingSiblingEntry[5]
strSucceedingSiblingComments = lstSucceedingSiblingEntry[2]
strSucceedingSiblingName = lstSucceedingSiblingEntry[1]
if intSucceedingSiblingParent == intPageParent:
# THEY HAVE A COMMON PARENT - THEY SEEM TO BE TRUE SIBLINGS!
intSucceedingSiblingSerial = intMaybeSS
break
if intSucceedingSiblingSerial > 0:
strSucceedingSiblingNav = "" % (strPathToHomeFolder, strSucceedingSiblingPath + "/" + strSucceedingSiblingFolder, strPageFileName, strSucceedingSiblingName, strPathToHomeFolder, strSucceedingSiblingName, strSucceedingSiblingName)
else:
strSucceedingSiblingNav = " " % (strPathToHomeFolder, "X", "X")
strNavigator = strPrecedingSiblingNav + strParentNav + strSucceedingSiblingNav
return strNavigator
# BUILD A SECTION WITH LIST OF CHILD PAGES
def fnBuildChildSection(intPageSerial):
# Site Map = Page Serial, Page Title, Page SubTitle, Page Author, Page Folder Name, Page Folder Path, Parent Page Serial, Depth
lstChildSection = ["","Pages","
"]
lstChildrenPages = []
for intPageNumber in range(intNumberOfPages+1):
lstThisPage = fnFindEntryInSiteMap(intPageNumber)
if lstThisPage[6] == intPageSerial:
lstChildrenPages.append(lstThisPage[0])
lstChildrenPages.sort()
for intChildPageSerial in lstChildrenPages:
lstThisPage = fnFindEntryInSiteMap(intChildPageSerial)
lstChildSection.append("
")
if len(lstChildrenPages):
return lstChildSection
else:
return []
# FIND ALL THE PARENTS OF THE PAGE - THEY ARE ALL META TAGS
def fnFindAllParents(intPageNumber, lstParentNumbers, lstParentNames):
# LOAD THE FILE NAME ITSELF
lstParentNumbers.append(intPageNumber)
lstParentNames.append(fnFindEntryInSiteMap(intPageNumber)[1])
# FIND THE IMMEDIATE PARENT TO RECURSE
intParentPageSerial = fnFindEntryInSiteMap(intPageNumber)[6]
# KEEP FINDING PARENTS OF PARENT UNTIL HOME PAGE IS REACHED
if intParentPageSerial > 0:
lstParentNumbers, lstParentNames = fnFindAllParents(intParentPageSerial, lstParentNumbers, lstParentNames)
return lstParentNumbers, lstParentNames
def fnBuildMenus(intPageSerial, lstMenuHtmls, intOriginalFolderDepth):
# FIRST PASS: FIND ALL PAGES AT SAME LEVEL AS PAGE ... IE ... ALL PAGES WITH SAME PARENT ... IE ... SIBLINGS
# FIND PARENT
lstSiblingSerials = []
lstMenuForThisPage = fnFindEntryInSiteMap(intPageSerial)
intParentPageSerial = lstMenuForThisPage[6]
# OVERRIDE WITH ORIGINAL FOLDER DEPTH
# intParentPageSerial = intOriginalFolderDepth
# FIND DEPTH OF THE PAGE
intThisPageDepth = intOriginalFolderDepth
# FIND SIBLINGS AND LOAD INTO LIST
# FOR EVERY PAGE IN THE SITE
for lstPageDetails in arrLstSiteMap:
# IF THE PAGE'S PARENT IS SAME AS THE ONE
intThisParentPageSerial = lstPageDetails[6]
if intThisParentPageSerial == intParentPageSerial:
# IT IS A SIBLING
lstSiblingSerials.append(lstPageDetails[0])
# ORDER THE LIST PER THE NUMERAL PREFIX
# MAX PREFIX = 99
lstSiblingOrderedSerials = []
for intPrefix in range(0, 100):
for intThisPageSerial in lstSiblingSerials:
strThisPageName = fnFindEntryInSiteMap(intThisPageSerial)[4]
intThisPagePrefix = int(fnFolderTitle(strThisPageName)[0])
# print ">>>>>>>>>>> %s|%s|%s" % (strThisPageName, intPrefix, intThisPagePrefix)
if intThisPagePrefix == intPrefix:
lstSiblingOrderedSerials.append(intThisPageSerial)
# BUILD HTML - HIGHLIGHT THIS PAGE THOUGH
intLevelCtr = len(lstMenuHtmls)+1
strThisLevelHtml = """
"""
# SHADE OF MENU DEPENDS ON DEPTH - TOP MOST IS BRIGHTEST
if intLevelCtr > 7:
intLevelCtr = 7
strMenuShade = lstMenuBgdColors[intLevelCtr]
intCtr1 = 0
for intSiblingPageSerial in lstSiblingOrderedSerials:
intCtr1 = intCtr1 + 1
lstPageDetails = fnFindEntryInSiteMap(intSiblingPageSerial)
# DEPTH OF THE PAGE THAT IS BEING PUT ON MENU DOES NOT MATTER
# intThisFolderDepth = lstPageDetails[7]
strPathToHomeFolder = ""
for intDepthCtr in range(0, intThisPageDepth-1):
strPathToHomeFolder = strPathToHomeFolder + "../"
strThisPageName = lstPageDetails[1]
strThisPageUrl = strPathToHomeFolder + lstPageDetails[5] + "/" + lstPageDetails[4] + "/" + strPageFileName
fnLog(5, "Menu from Page [" + lstMenuForThisPage[1] + "] TO Page [" + strThisPageName + "], the RELATIVE URL is [" + strThisPageUrl + "]")
strThisPageAlt = lstPageDetails[2]
# FOR THIS PAGE,
if intSiblingPageSerial == intPageSerial:
# DEACTIVATE LINK FOR THIS SPECIFIC PAGE (YOU ARE ALREADY ON IT!)
if len(lstMenuHtmls) == 0:
# strThisLevelHtml = strThisLevelHtml + "| This Page: %s " % (strThisPageUrl, strThisPageAlt, strThisPageName)
strThisLevelHtml = strThisLevelHtml + """
%s
""" % (intLevelCtr, intCtr1, strThisPageName)
# ELSE IF A DIRECT PARENT, THEN SHOW LINK, BUT HIGHLIGHT AS A PARENT
else:
# strThisLevelHtml = strThisLevelHtml + "| This Page: %s " % (strThisPageUrl, strThisPageAlt, strThisPageName)
strThisLevelHtml = strThisLevelHtml + """
"""
intCtr1 = 0
for intSiblingPageSerial in lstSiblingOrderedSerials:
intCtr1 = intCtr1 + 1
lstPageDetails = fnFindEntryInSiteMap(intSiblingPageSerial)
strThisPageName = lstPageDetails[1]
strThisPageUrl = "/" + lstPageDetails[5] + "/" + lstPageDetails[4] + "/" + strPageFileName
strThisPageAlt = lstPageDetails[2]
# FOR THIS PAGE,
if intSiblingPageSerial == intPageSerial:
# DEACTIVATE LINK FOR THIS SPECIFIC PAGE (YOU ARE ALREADY ON IT!)
if len(lstMenuHtmls) == 0:
strThisLevelHtml = strThisLevelHtml + """
""" % (intLevelCtr, intCtr1, "#aa4400")
# ELSE IF A DIRECT PARENT, THEN SHOW LINK, BUT HIGHLIGHT AS A PARENT
else:
strThisLevelHtml = strThisLevelHtml + """
"""
lstMenuHtmls.append(strThisLevelHtml)
# RECURSE FOR PARENT
if intParentPageSerial > 0:
fnBuildMenus(intParentPageSerial, lstMenuHtmls, intOriginalFolderDepth)
fnLog(6, "List of Menu Links =: [%s]" % lstMenuHtmls)
return lstMenuHtmls
def fnBuildChildMenu(intPageSerial):
# FIRST PASS: FIND ALL PAGES WITH THIS ONE AS PARENT ... IE ... CHILDREN
# FIND PARENT
lstSiblingSerials = []
lstMenuForThisPage = fnFindEntryInSiteMap(intPageSerial)
# FIND DEPTH OF THE PAGE
intThisPageDepth = lstMenuForThisPage[7]
# intParentPageSerial = fnFindEntryInSiteMap(intPageSerial)[6]
# FIND SIBLINGS AND LOAD INTO LIST
# FOR EVERY PAGE IN THE SITE
for lstPageDetails in arrLstSiteMap:
# IF THE PAGE'S PARENT IS SAME AS THIS ONE
intThisParentPageSerial = lstPageDetails[6]
if intThisParentPageSerial == intPageSerial:
# IT IS A CHILD
lstSiblingSerials.append(lstPageDetails[0])
# ORDER THE LIST PER THE NUMERAL PREFIX
# MAX PREFIX = 99
lstSiblingOrderedSerials = []
for intPrefix in range(0, 100):
for intThisPageSerial in lstSiblingSerials:
strThisPageName = fnFindEntryInSiteMap(intThisPageSerial)[4]
intThisPagePrefix = int(fnFolderTitle(strThisPageName)[0])
# print ">>>>>>>>>>> %s|%s|%s" % (strThisPageName, intPrefix, intThisPagePrefix)
if intThisPagePrefix == intPrefix:
lstSiblingOrderedSerials.append(intThisPageSerial)
# BUILD HTML
strSampleMenuHtml = """
""" % (intTableWidth, intTableWidth - 250, intTableWidth - 275, strImageBackground, strImageLink, intImageWidth, strImageCaption, strImageLink, strImageCaption)
strPageContent = strPageContent + strImageHtml
intImageCounter = intImageCounter + 1
return strPageContent, intImageCounter
# CREATES ALL THE WEB PAGES
def fnPublishFolder(intTotalPages):
for intPageNumber in range(0,intTotalPages+1):
# Site Map = Page Serial, Page Title, Page SubTitle, Page Author, Page Folder Name, Page Folder Path, Parent Page Serial, Depth
lstPageEntry = fnFindEntryInSiteMap(intPageNumber)
strFolderPath = lstPageEntry[5]
strFolderName = lstPageEntry[4]
intPageSerial = intPageNumber
try:
pass
except:
pass
if 1:
# LOCATE FOLDER SERIAL NUMBER
lstFolderContents = os.listdir(strRootPath + "/" + strFolderPath + "/" + strFolderName)
# IF SERIAL NUMBER FOUND, THEN
if strMetaSerialFileName in lstFolderContents:
# LOAD THE SERIAL NUMBER AND RELATED INFO FROM ANALYSIS PASS
intPageSerial = int(fnCleanReadLines(strRootPath + "/" + strFolderPath + "/" + strFolderName + "/" + strMetaSerialFileName)[0])
lstThisFolder = fnFindEntryInSiteMap(intPageSerial)
intThisFolderDepth = lstThisFolder[7]
strPathToHomeFolder = ""
for intDepthCtr in range(0, intThisFolderDepth-1):
strPathToHomeFolder = strPathToHomeFolder + "../"
fnLog(5, "Folder Serial = [%d] Map = [%s]" % (intPageSerial, lstThisFolder))
# DETERMINE BREADCRUMBS FOR THIS PAGE
strHtmlBreadCrumbs = fnBreadCrumbs("", intPageSerial, intThisFolderDepth, 1)
fnLog(5, strHtmlBreadCrumbs)
# LOAD META DATA
# AUTHOR INFO (MULTIPLE SUPPORTED)
if strMetaAuthorFileName in lstFolderContents:
lstAuthorText = fnCleanReadLines(strRootPath + "/" + strFolderPath + "/" + strFolderName + "/" + strMetaAuthorFileName)
else:
lstAuthorText = [strDefaultMetaAuthor]
strAuthorHtml = ""
for strAuthorText in lstAuthorText:
if len(strAuthorHtml) == 0:
strAuthorHtml = strAuthorText
else:
strAuthorHtml = strAuthorHtml + ", " + strAuthorText
# TITLE AND SUB-TITLE WERE LOADED IN FIRST PASS
strTitleText = lstPageEntry[1]
strSubTitleText = lstPageEntry[2]
# IF VERSION INFO EXISTS, LOAD THE LIST, BUT USE ONLY THE TOP VALUE
# IF IT DOESN'T, ASSUME IT IS VERSION 1.0 AND INIT THE TIME TO THE LAST MODIFY TIME OF THE CONTENT FILE
# AND IF THAT FAILS, IT IS SIMPLY VERSION 1.0 WITH NO TIME ASSIGNMENT
# DATE SHOULD BE PROVIDED IN YYYYMMDD FORMAT
if strMetaVersionFileName in lstFolderContents:
lstVersionText = fnCleanReadLines(strRootPath + "/" + strFolderPath + "/" + strFolderName + "/" + strMetaVersionFileName)
strVersionText = lstVersionText[0]
lstVersionDetails = string.split(strVersionText, "|")
# IF VERSION INFO INCLUDES TIME, CONVERT IT
if len(lstVersionDetails) > 1:
strVersionDate = lstVersionDetails[1]
strVersionDate = fnConvertDate(strVersionDate)
lstVersionText = [lstVersionDetails[0] + " of " + strVersionDate]
# ELSE USE THE VERSION INFO AND CALC TIME FROM CONTENT FILE UPDATE DATE
else:
if strMetaContentFileName in lstFolderContents:
lstVersionText = ["%s of %s" % (lstVersionDetails[0], time.asctime(time.localtime(os.stat(strRootPath + "/" + strFolderPath + "/" + strFolderName + "/" + strMetaContentFileName).st_mtime)))]
elif strMetaSpecialContentFileName in lstFolderContents:
lstVersionText = ["%s of %s" % (lstVersionDetails[0], time.asctime(time.localtime(os.stat(strRootPath + "/" + strFolderPath + "/" + strFolderName + "/" + strMetaSpecialContentFileName).st_mtime)))]
else:
pass
else:
# ELSE DEFAULT THE VERSION INFO AND CALC THE TIME
try:
# lstVersionText = ["Version 1.0"]
lstVersionText = ["%s of %s" % (strDefaultMetaVersion, time.asctime(time.localtime(os.stat(strRootPath + "/" + strFolderPath + "/" + strFolderName + "/" + strMetaContentFileName).st_mtime)))]
fnLog(6, "Calculated version of [%s] = [%s]" % (strFolderName, lstVersionText))
# AND IF ALL ELSE FAILS, JUST MENTION V INFO
except:
lstVersionText = [strDefaultMetaVersion]
strVersionHtml = ""
for strVersionText in lstVersionText:
if len(strVersionHtml) == 0:
strVersionHtml = strVersionText
else:
strVersionHtml = strVersionHtml + ", " + strVersionText
# LOAD META TAGS
if strMetaTagsFileName in lstFolderContents:
lstMetaTagText = fnCleanReadLines(strRootPath + "/" + strFolderPath + "/" + strFolderName + "/" + strMetaTagsFileName)
else:
lstMetaTagText = lstDefaultMetaTags
# LOAD TYPES OF MEDIA FILES SUPPORTED
if strMetaMediaFileTypesFileName in lstFolderContents:
lstMediaFileTypes = fnCleanReadLines(strRootPath + "/" + strFolderPath + "/" + strFolderName + "/" + strMetaMediaFileTypesFileName)
else:
lstMediaFileTypes = strDefaultMetaMediaFileTypes
# LOAD LIST OF LINKS - REFERENCES (ABSOLUTE) AND ATTACHMENTS (LOCAL OR ABSOLUTE)
if strMetaReferenceLocalLinksFileName in lstFolderContents:
lstLocalLinks = fnCleanReadLines(strRootPath + "/" + strFolderPath + "/" + strFolderName + "/" + strMetaReferenceLocalLinksFileName)
else:
lstLocalLinks = strDefaultMetaReferenceLocalLinks
if strMetaReferenceWebLinksFileName in lstFolderContents:
lstWebLinks = fnCleanReadLines(strRootPath + "/" + strFolderPath + "/" + strFolderName + "/" + strMetaReferenceWebLinksFileName)
else:
lstWebLinks = strDefaultMetaReferenceWebLinks
# LOAD PREFERRED FONTS FOR THIS PAGE
if strMetaFontStyleFileName in lstFolderContents:
lstFontTypes = fnCleanReadLines(strRootPath + "/" + strFolderPath + "/" + strFolderName + "/" + strMetaFontStyleFileName)
else:
lstFontTypes = lstDefaultMetaFontStyle
strFontHtml = ""
for strFontText in lstFontTypes:
if len(strFontHtml) == 0:
strFontHtml = strFontText
else:
strFontHtml = strFontHtml + ", " + strFontText
# LOAD PREFERRED BACKGROUND FOR THIS PAGE
strBKGD = strDefaultBKGD
if strMetaBKGDFileName in lstFolderContents:
strBKGD = fnCleanReadLines(strRootPath + "/" + strFolderPath + "/" + strFolderName + "/" + strMetaBKGDFileName)[0]
if strBKGD == "":
strBKGD = strDefaultBKGD
if strBKGD[0] == "#":
strBKGDFile = ""
strBKGDColor = strBKGD
else:
strBKGDFile = strBKGD
strBKGDColor = ""
strBKGD = strPanelBackground
# BUILD META ELEMENTS FOR FACEBOOK
strMetaTitle = "" % strTitleText
strMetaDescription = "" % strSubTitleText
lstMedia = lstLocalLinks
for strWebLink in lstWebLinks:
lstMedia.append(strWebLink)
binFoundAnImage = 0
for strMedia in lstMedia:
lstLinkName = string.split(strMedia, "|")
if len(lstLinkName) > 1:
lstLinkExt = string.split(lstLinkName[0], ".")
if len(lstLinkExt) > 1:
if string.lower(lstLinkExt[1]) in strDefaultMetaMediaFileTypes:
binFoundAnImage = 1
strMetaImageLink = lstLinkName[0]
strMetaImageDesc = lstLinkName[1]
if strMetaImageLink[0:4] == "http":
strMetaImageLink = strMetaImageLink
elif strMetaImageLink[0:1] == "/":
strMetaImageLink = strSiteLink + strMetaImageLink
else:
strMetaImageLink = strSiteLink + "/" + strFolderPath + "/" + strFolderName + "/" + strMetaImageLink
break
if binFoundAnImage == 0:
strMetaImageLink = "%s/%s/%s" % (strSiteLink, strLogoFolder, strDefaultLogoFile)
strMetaImageDesc = "Sandhir"
strMetaImageLink = string.replace(strMetaImageLink, "/.//", "/")
strMetaImage = "" % (strMetaImageLink)
# BUiLD META ELEMENTS FOR GOOGLE SPIDERS
strMetaTags = ""
# ADD ALL PARENT PAGE NAMES AS META TAGS !!!! HOW COOL IS THAT?
lstPageParentSerials, lstAdditionalMetaTags = fnFindAllParents(intPageNumber, [], [])
for strMetaTag in lstMetaTagText:
if len(strMetaTags) == 0:
strMetaTags = strMetaTag
else:
strMetaTags = strMetaTags + ", " + strMetaTag
for strMetaTag in lstAdditionalMetaTags:
strMetaTags = strMetaTags + ", " + strMetaTag
strMetaTags = "" % strMetaTags
fnLog(5, "Meta Data = [%s|%s|%s|%s]" % (strMetaTitle, strMetaDescription, strMetaImage, strMetaTags))
# BUILD OTHER META ELEMENTS
strPageGlobalUrl = strSiteLink + "/" + strFolderPath + "/" + strFolderName + "/" + strPageFileName
strPageGlobalUrl = string.replace(strPageGlobalUrl, "/.//", "/")
strPageGlobalDes = "%s - %s" % (strTitleText, strSubTitleText)
# ===== LOADING OF THE LIST OF BANNER IMAGES IS DONE GLOBALLY =====
# BUILD HTML FOR ALL THE LINKS
strLinksHtml = "
"
lstPageImage = []
for strWebLink in lstMedia:
# IF IT IS A LOCAL LINK PUT AN ATTACHMENT ICON
binAttach = 1
if strWebLink[0:4] == "http":
binAttach = 0
if binAttach:
strThisIcon = strAttachIcon
strType = ""
else:
# ELSE, PUT A WEB ICON
strThisIcon = strWebLinkIcon
strType = ""
strTarget = ""
if binOpensNewPage:
strTarget = " target='_blank' "
strLink = string.split(strWebLink, "|")
strLinksHtml = strLinksHtml + "
" % (strPathToHomeFolder + strThisIcon, strLink[0], strTarget, strLink[1])
# IF THE LINK IS FOR AN IMAGE, LOAD INTO IMAGE LIST
lstLinkExt = string.split(strLink[0], ".")
if len(lstLinkExt) > 1:
if string.lower(lstLinkExt[1]) in strDefaultMetaMediaFileTypes:
lstPageImage.append(strWebLink)
strLinksHtml = strLinksHtml + "
"
# BUILD ALL THE TOP LINKS - FONT-SIZE, PRINT, FACEBOOK, TWITTER, EMAIL, SITE MAP
# PERFORMED BELOW
# FIND PEER AND PARENT MENUS
lstMenuHtmls = fnBuildMenus(intPageNumber, [], intThisFolderDepth)
lstMenuHtmls.reverse()
strMenus = ""
for strMenuHtml in lstMenuHtmls:
strMenus = strMenus + strMenuHtml + ""
# FIND CHILD MENUS
strChildMenuHtml = fnBuildChildMenu(intPageNumber)
# BUILD FOOTER - VERSION, COPYRIGHT, PRIVACY, SUPPORT (HTML, CSS, LINUX, PYTHON), META TAGS
# LOAD THE CONTENT
if strMetaContentFileName in lstFolderContents:
lstContentText = fnCleanReadLines(strRootPath + "/" + strFolderPath + "/" + strFolderName + "/" + strMetaContentFileName)
else:
lstContentText = [strDefaultMetaContent]
if strMetaSpecialContentFileName in lstFolderContents:
lstSpecialContentText = fnCleanReadLines(strRootPath + "/" + strFolderPath + "/" + strFolderName + "/" + strMetaSpecialContentFileName)
else:
lstSpecialContentText = [strDefaultMetaSpecialContent]
# If Auto generated content exists (such as album pages, etc), special content is replaced with it
if strMetaAutoContentFileName in lstFolderContents:
lstSpecialContentText = fnCleanReadLines(strRootPath + "/" + strFolderPath + "/" + strFolderName + "/" + strMetaAutoContentFileName)
# ADD A SECTION AT THE BOTTOM FOR CHILD PAGES
lstChildSection = fnBuildChildSection(intPageSerial)
if len(lstChildSection):
for strChildSectionLine in lstChildSection:
lstContentText.append(strChildSectionLine)
# SPECIAL CONTENT IS APPENDED TO NORMAL CONTENT - NO SPECIAL HANDLING AS YET
# for strSpecialContentText in lstSpecialContentText:
# lstContentText.append(strSpecialContentText)
# BUILD ALL THE IMAGES
# USE THE IMAGE LIST BUILT OUT OF ATTACHMENT/WEBLINK LIST
# WE EVENLY SPACE THEM BETWEEN CONTENT PARAS
intNumberOfContentParas = len(lstContentText) + len(lstSpecialContentText)
intNumberOfPageImages = len(lstPageImage)
if intNumberOfContentParas > intNumberOfPageImages:
if intNumberOfPageImages == 0:
intParasAfterImage = 1
else:
intParasAfterImage = int(float(intNumberOfContentParas) / float(intNumberOfPageImages))
intImagesAfterPara = 1
else:
intParasAfterImage = 1
if intNumberOfContentParas == 0:
intImagesAfterPara = 1
else:
intImagesAfterPara = int(float(intNumberOfPageImages) / float(intNumberOfContentParas))
if intImagesAfterPara > intMaxNumberImagesPerRow:
intImagesAfterPara = intMaxNumberImagesPerRow
# BUILD THE CONTENT BODY
strPageContent = ""
intParaCounter = 0
intImageCounter = 0
# MARKUP THE CONTENT WITH APPROPRIATE HTML
# , , AS
"
# IF LINES END WITH TAGS '>' THEN DO NOT PUT
if (len(strContentTxt)>0):
if (strContentTxt[len(strContentTxt)-1] == '>'):
strPageContent = strPageContent + "\n" + strContentTxt
# ELSE ADD A CR / LINE CHANGE /
else:
strPageContent = strPageContent + "\n" + strContentTxt + " "
else:
strPageContent = strPageContent + "\n" + strContentTxt + " "
# SPECIAL CONTENT LINES ARE PLACED AS IS, INTERSPERSED WITH IMAGES
if len(lstSpecialContentText) > 0:
if len(lstSpecialContentText[0]) >= 0:
# strPageContent = strPageContent + "