Index: qPloneSkinDump/trunk/skin_template/Extensions/Install.py
===================================================================
--- qPloneSkinDump/trunk/skin_template/Extensions/Install.py	(revision 1)
+++ qPloneSkinDump/trunk/skin_template/Extensions/Install.py	(revision 74)
@@ -1,126 +1,25 @@
-import string
-from StringIO import StringIO
-from zLOG import LOG, INFO
 from Products.CMFCore.utils import getToolByName
-from Products.%(SKIN_PRODUCT_NAME)s.config import *
-from Products.%(SKIN_PRODUCT_NAME)s.Extensions.utils import *
 
-CHECKED_MESSAGE = "The base installation checkings completed."
+from Products.%(product_name)s.config import GS_INSTALL_PROFILE
+from Products.%(product_name)s.config import GS_AFTERINSTALL_PROFILE
+from Products.%(product_name)s.config import GS_UNINSTALL_PROFILE
 
-def prepareInstallation(portal, pp, product, out):
-    checkSuccessInstall(product)
-    uninstallOtherSkinProducts(portal)
-    if not ('uninstall_properties' in pp.objectIds()) :
-        pp.addPropertySheet(id='uninstall_properties', title= 'uninstall_properties')
-        print >> out, "Created 'portal_properties.uninstall_properties' PropertySheet (UP) for backup purpose"
+def install(self, reinstall=False):
+    """ Install skin with GenericSetup install profile
+    """
+    ps = getToolByName(self, 'portal_setup')
+    (ps.aq_base).__of__(self).runAllImportStepsFromProfile(GS_INSTALL_PROFILE)
 
-def checkSuccessInstall(product):
-    # Check for successfully completed 1 installation step
-    transcript = getattr(product,'transcript',None)
-    if transcript:
-        msg = str(transcript[0]['msg'])
-        if msg.find(CHECKED_MESSAGE) < 0 :
-            product.log("First part installation procedure not completed - installation terminated.")
-            raise
+def afterInstall(self, reinstall, product):
+    """ Install zexp objects and other dependent objects.
+        Perform this step here for prevent removing objects on uninstallation.
+    """
+    ps = getToolByName(self, 'portal_setup')
+    (ps.aq_base).__of__(self).runAllImportStepsFromProfile(GS_AFTERINSTALL_PROFILE)
 
-def uninstallOtherSkinProducts(portal):
-    qi=getToolByName(portal, 'portal_quickinstaller', None)
-    if not qi:
-        raise Exception("Can't work without QuickInstaller tool.")
-    # Get installed products
-    installed_products = [getattr(qi, p_dict['id']) \
-                          for p_dict in qi.listInstalledProducts()
-                          if p_dict['id'] != PRODUCT_NAME]
-    seek_str = "%%s generated product" %% GENERATOR_PRODUCT
-    installed_skin_products = []
-    # Looking for installed skin-products
-    for p in installed_products:
-        transcript = p.getTranscriptAsText()
-        if transcript.find(seek_str) >= 0 :
-            installed_skin_products.append(p.getId())
-    # Uninstall found skin-products
-    if installed_skin_products:
-        qi.uninstallProducts(products=installed_skin_products)
-
-def install(self):
-    # Checking base condition for installation
-    skinsTool = getToolByName(self, 'portal_skins')
-    # Checking for BASE_SKIN_NAME presenting in portal
-    skin_names = skinsTool.getSkinSelections()
-    if not BASE_SKIN_NAME in skin_names:
-        raise AttributeError("Impossible installation without %%s skin." %% BASE_SKIN_NAME)
-    # Checking for presenting lower_SKIN_NAME directory in portal skins
-    lower_SKIN_NAME = string.lower(SKIN_NAME)
-    if lower_SKIN_NAME in skinsTool.objectIds():
-        raise AttributeError("%%s skin layer already exist in portal skins. Installation Impossible." %% lower_SKIN_NAME)
-    return CHECKED_MESSAGE
-
-# For prevent quickInstaller's intervention in uninstall process - use afterInstall
-def afterInstall(self,product,reinstall):
-    out=StringIO()
-    # get all needed tools and some portal's core objects
-    portal = getToolByName(self, 'portal_url').getPortalObject()
-    pp = getToolByName(portal, 'portal_properties')
-    portal_css = getToolByName(portal, 'portal_css', None)
-    portal_js = getToolByName(portal, 'portal_javascripts', None)
-    # Make main prepare procedures
-    prepareInstallation(portal, pp, product, out)
-    pp_up = pp.uninstall_properties
-    # Install skin
-    installSkin(portal, pp_up, out)
-    # Register css resources
-    if portal_css and DOES_COSTOMIZE_CSS:
-        registerResource(pp_up, portal_css, portal_css.registerStylesheet, out \
-                        ,CSS_LIST, SKIN_CSS_REGDATA, 'q_registered_css', CSS_REG_PROPS)
-        print >> out, "Completed tuning CSS registry for new skin needs."
-    # Register js resources
-    if portal_js and DOES_COSTOMIZE_JS:
-        registerResource(pp_up, portal_js, portal_js.registerScript, out \
-                        ,JS_LIST, SKIN_JS_REGDATA, 'q_registered_js', JS_REG_PROPS)#---installJS---
-        print >> out, "Completed tuning JS registry for new skin needs."
-    # Customize slots    
-    if LEFT_SLOTS or RIGHT_SLOTS:
-        customizeSlots(portal, pp_up, out)
-    # Import object(s) to portal
-    if checkIfImport():
-        res_import = performImportToPortal(portal)
-        print >> out, res_import
-    # FINAL customization call additional functions from config 
-    if FINAL_CUSTOMIZATION_FUNCTIONS:
-        dummy = [func(portal, out) for func in FINAL_CUSTOMIZATION_FUNCTIONS]
-    print >> out, "%%s generated product." %% GENERATOR_PRODUCT
-    print >> out, '=== Installation successfully completed. ==='
-    product.log(out.getvalue())
-    product._p_changed = 1 #XXX:NEED for stable writing 'out' log to qi on afterinstallation.
-    return out.getvalue()
-
-def uninstall(self):
-    # get all needed tools and some portal's core objects
-    portal = self.portal_url.getPortalObject()
-    skinsTool = getToolByName(portal, 'portal_skins')
-    pp = getToolByName(portal, 'portal_properties')
-    portal_css = getToolByName(portal, 'portal_css', None)
-    portal_js = getToolByName(portal, 'portal_javascripts', None)
-    # Get all properies, saving during installation, for uninstalling
-    actual_skin_name = getProperty(pp, 'uninstall_properties', 'q_actual_skin_name',default=SKIN_NAME)
-    initial_skin = getProperty(pp, 'uninstall_properties', 'q_default_skin',default="")
-    original_css_list = getProperty(pp, 'uninstall_properties', 'q_registered_css')
-    original_js_list = getProperty(pp, 'uninstall_properties', 'q_registered_js')
-    orig_left_slots = getProperty(pp, 'uninstall_properties','q_left_slots')
-    orig_right_slots = getProperty(pp, 'uninstall_properties','q_right_slots')
-    # Remove 'uninstall_properties' from portal_properties
-    if 'uninstall_properties' in pp.objectIds() :
-        pp.manage_delObjects(ids=['uninstall_properties',])
-    # Uninstall skin
-    uninstallSkin(skinsTool, actual_skin_name, initial_skin)
-    # Unregister skin's CSS-es from portal_css. Only for Plone 2.1+
-    if portal_css and DOES_COSTOMIZE_CSS:
-        uninstallResource(portal_css, original_css_list, CSS_LIST, portal_css.registerStylesheet)
-    # Unregister skin's JS-s from portal_javascripts. Only for Plone 2.1+
-    if portal_js and DOES_COSTOMIZE_JS:
-        uninstallResource(portal_js, original_js_list, JS_LIST, portal_js.registerScript)
-    # Return site's column slots list unless Skin product installation
-    if orig_left_slots:
-        portal.left_slots = tuple(orig_left_slots)
-    if orig_right_slots:
-        portal.right_slots = tuple(orig_right_slots)
+def uninstall(self, reinstall=False):
+    """ Uninstall skin with GenericSetup uninstall profile
+    """
+    ps = getToolByName(self, 'portal_setup')
+    (ps.aq_base).__of__(self).runAllImportStepsFromProfile(GS_UNINSTALL_PROFILE)
+    
Index: qPloneSkinDump/trunk/skin_template/Extensions/__init__.py
===================================================================
--- qPloneSkinDump/trunk/skin_template/Extensions/__init__.py	(revision 1)
+++ qPloneSkinDump/trunk/skin_template/Extensions/__init__.py	(revision 74)
@@ -1,2 +1,1 @@
-# this file is here to make Install.py importable.
-# we need to make it non-zero size to make winzip cooperate
+#
Index: qPloneSkinDump/trunk/skin_template/Extensions/utils.py
===================================================================
--- qPloneSkinDump/trunk/skin_template/Extensions/utils.py	(revision 1)
+++ 	(revision )
@@ -1,416 +1,0 @@
-import os, sys, re, string
-from StringIO import StringIO
-from time import gmtime, strftime
-from zLOG import LOG, INFO
-from zExceptions import BadRequest
-from App.config import getConfiguration
-from Products.CMFCore.utils import getToolByName
-from Products.CMFCore.DirectoryView import addDirectoryViews
-from Products.%(SKIN_PRODUCT_NAME)s.config import *
-
-######################################################################
-##                      IMPORTING UTILS                             ##
-######################################################################
-osp = os.path
-ALLOWED_IMPORT_POLICY = ["only_new", "backup", "overwrite"]
-INTRO_TO_INSTANCE = "< Started copying object files from Product import directory to Instance one."
-SUMMARY_TO_INSTANCE = "> Finished copying."
-INTRO_TO_ROOT = "< Started import %%s file[s] with '%%s' policy."
-SUMMARY_TO_ROOT = "> Finished importing."
-INTRO_CLEAN = "< Started cleaning Instance import directory."
-SUMMARY_CLEAN = "> Finished cleaning."
-CREXP_INVALID_ID = re.compile('^The id \"(.*?)\" is invalid - it is already in use.$', re.DOTALL|re.IGNORECASE|re.MULTILINE)
-CSS_BASE_IDS_QPSD053 = ['id','expression','enabled','cookable','media','rel','title','rendering']   # supporting qPSD-0.5.3 version
-################    CHECK IMPORTING    ################
-def checkIfImport():
-    """ Return if perform importing, based on checking 
-        *zexp files in <SkinProduct>/import directory.
-    """
-    instance_ipath, product_ipath = getImportedPathes()
-    product_ilist = [i for i in os.listdir(product_ipath) \
-                     if osp.isfile(osp.join(product_ipath,i)) and i.endswith('.zexp')]
-    if product_ilist:
-        return 1
-    return 0
-
-################    IMPORTING TO PLONE'S IMPORT DIR   ################
-def getImportedPathes():
-    """ Return Plone instance and Skin product import pathes."""
-    # Based on instance path, construct import pathes 
-    cfg = getConfiguration()
-    instance_ipath = osp.join(cfg.instancehome, "import")
-    product_ipath = osp.join(cfg.instancehome, 'Products', PRODUCT_NAME, "import")
-    # Check presence of Product import directory
-    if not osp.isdir(product_ipath):        
-        raise BadRequest, "Skin Product's import directory '%%s' - does not exist or is'nt direcory" %% product_ipath
-    # Check presence of Instance import directory
-    if not osp.isdir(instance_ipath):
-        raise BadRequest, "Instance import directory '%%s' - does not exist or isn't direcory" %% instance_ipath
-    return [instance_ipath, product_ipath]
-
-def copyFile(src_dir, dst_dir, f_name):
-    """ Copy file from src_dir to dst_dir under original name."""
-    try:
-        src_file = open(osp.join(src_dir, f_name),"rb")
-        dst_file = open(osp.join(dst_dir, f_name),"wb")
-        dst_file.write(src_file.read())
-        dst_file.close()
-        src_file.close()
-    except Exception, e:
-        msg = "!!! In copying files from <%%s> dir to <%%s> dir exception occur. Details: %%s." %% (src_dir,dst_dir, str(e))
-        print >> import_out, msg
-        LOG('performImportToPortal',INFO,'copyFile', msg)
-
-def moveToTemp(same_instance_files, instance_ipath, temp_dir_path):
-    """ Move samenamed files from Instanse's dir to temp dir."""
-    os.mkdir(temp_dir_path) # Create temp back_[date] dir
-    try:
-        [copyFile(instance_ipath, temp_dir_path, f_name) for f_name in same_instance_files]
-        [os.remove(osp.join(instance_ipath, f_name)) for f_name in same_instance_files]
-    except Exception, e:
-        msg = "!!! Exception occur during moving files from Instance's dir to temp dir. Detaile:%%s." %% str(e)
-        print >> import_out, msg
-        LOG('performImportToPortal',INFO,'moveToTemp', msg)
-    
-def copyToInstanceImport():
-    """ Perform copying imported files from <SkinProduct>/import dir
-        to Plone's instance import dir.
-    """
-    print >> import_out, INTRO_TO_INSTANCE
-    instance_ipath, product_ipath = getImportedPathes()
-    # Compose temp dir back_[date] dir path in Instance import directory
-    temp_dir_id = "back_%%s" %% strftime("%%Y%%m%%d%%H%%M%%S", gmtime())
-    temp_dir_path = osp.join(instance_ipath, temp_dir_id)
-    # Get *.zexp files from Skin Product's import dir and Plone's instance import dir files
-    product_ilist = [i for i in os.listdir(product_ipath) \
-                     if osp.isfile(osp.join(product_ipath,i)) and i.endswith('.zexp')]
-    instance_ilist = [i for i in os.listdir(instance_ipath) \
-                      if osp.isfile(osp.join(instance_ipath,i)) and i.endswith('.zexp')]
-    # Check for presence samenamed files in Instance and Product import directories.
-    same_instance_files = [f_name for f_name in instance_ilist if f_name in product_ilist]
-    if same_instance_files:
-        moveToTemp(same_instance_files, instance_ipath, temp_dir_path)
-    # Copy all *zexp files from Product's import dir to Instance's import dir
-    [copyFile(product_ipath, instance_ipath, f_name) for f_name in product_ilist]
-    print >> import_out, SUMMARY_TO_INSTANCE
-    return [instance_ipath, product_ipath, temp_dir_path, product_ilist]
-
-################    IMPORTING TO PORTAL   ################
-def importObject(portal, file_name):
-    """ Work around old Zope bug in importing."""
-    try:
-        portal.manage_importObject(file_name)
-    except:
-        portal._p_jar = portal.Destination()._p_jar
-        portal.manage_importObject(file_name)
-
-def makeBackUp(portal, portal_objects, temp_dir_path, obj_id):
-    """ Perfom backup same named portal objects in temp folder."""
-    # Get id of temp folder-object
-    durty_path,temp_id = osp.split(temp_dir_path)
-    if not temp_id:
-        durty_path,temp_id = osp.split(durty_path)
-    # Get temp folder-object
-    if temp_id not in portal_objects:
-        portal.invokeFactory('Folder', id=temp_id)
-        print >> import_out, "! Created '%%s' backup directory with same-ids " \
-                             "objects from portal root." %% temp_id
-    temp_dir = getattr(portal, temp_id)
-    # Move object with same id to temp folder-object
-    get_transaction().commit(1)
-    obj = portal.manage_cutObjects(ids=[obj_id])
-    temp_dir.manage_pasteObjects(obj)
-    print >> import_out, "! '%%s' Object moved from portal root to '%%s' backup directory." %% (obj_id, temp_id)
-
-def performImport(portal, temp_dir_path, file_name):
-    """ Importing an object to portal."""
-    portal_objects = portal.objectIds()
-    try:
-        portal.manage_importObject(file_name)
-    except Exception, e:
-        msg = str(e)
-        is_invalid_id = CREXP_INVALID_ID.match(msg)
-        if is_invalid_id:
-            obj_id = is_invalid_id.group(1)
-            if IMPORT_POLICY == "only_new":
-                msg = "! Object with '%%s' id was not importing because it's already exist " \
-                      "in portal root." %% obj_id
-                print >> import_out, msg
-            elif IMPORT_POLICY == "backup":
-                makeBackUp(portal, portal_objects, temp_dir_path, obj_id)
-                importObject(portal, file_name)
-            elif IMPORT_POLICY == "overwrite":
-                portal.manage_delObjects(ids=[obj_id])
-                importObject(portal, file_name)
-        else:
-            # work around old Zope bug in importing
-            portal._p_jar = portal.Destination()._p_jar
-            portal.manage_importObject(file_name)
-
-def importToPortalRoot(portal, product_file_names, temp_dir_path):
-    """ Import all objects from *zexp files to portal root (based on IMPORT_POLICY)."""
-    if not IMPORT_POLICY in ALLOWED_IMPORT_POLICY:
-        raise Exception("%%s - wrong import policy in '%%s/config.py' file. Must be one of the %%s" \
-                        %% (IMPORT_POLICY, PRODUCT_NAME, ALLOWED_IMPORT_POLICY) )
-    print >> import_out, INTRO_TO_ROOT %% (product_file_names, IMPORT_POLICY)
-    for file_name in product_file_names:
-        try:
-            performImport(portal, temp_dir_path, file_name)
-        except Exception, error:
-            msg = '!!! Under "%%s" policy importing exception occur: %%s.' %% (IMPORT_POLICY, str(error))
-            print >> import_out, msg
-            LOG('performImportToPortal',INFO,'importToPortalRoot', msg)
-    print >> import_out, SUMMARY_TO_ROOT
-
-################    CLEANING PLONE'S IMPORT DIR   ################
-def cleanInstanceImport(instance_ipath, product_file_names, temp_dir_path):
-    """ Cleaning Plone's import dir."""
-    print >> import_out, INTRO_CLEAN
-    # Erase all copied *zexp files from Instance's import dir
-    for f_name in product_file_names:
-        f_path = osp.join(instance_ipath, f_name)
-        if osp.exists(f_path) and osp.isfile(f_path):
-            os.remove(f_path)
-        else:
-            msg = '! "%%s" file was not deleted from "%%s" import directory.' %%\
-                   (f_name, osp.join(instance_ipath))
-            print >> import_out, msg
-            LOG('performImportToPortal',INFO,'cleanInstanceImport', msg)
-    # Move all files from temp back_[date] dir to Instance's import dir
-    if osp.exists(temp_dir_path) and osp.isdir(temp_dir_path):
-        f_names = os.listdir(temp_dir_path)
-        try:
-            [copyFile(temp_dir_path, instance_ipath, f_name) for f_name in f_names]
-            [os.remove(osp.join(temp_dir_path, f_name)) for f_name in f_names]
-            # Erase temp back_[date] dir
-            os.rmdir(temp_dir_path)
-        except Exception, e:
-            msg = "!!! In moving files from temp dir to Instance's import dir exception occur."
-            print >> import_out, msg
-            LOG('performImportToPortal',INFO,'moveFromTempToImport', msg)
-    print >> import_out, SUMMARY_CLEAN
-
-################    MAIN    ################
-def performImportToPortal(portal):
-    """ Import objects from Skin Product to Portal root."""
-    globals()['import_out'] = StringIO()
-    instance_ipath, product_ipath, temp_dir_path, product_file_names = copyToInstanceImport()
-    if product_file_names:
-        importToPortalRoot(portal, product_file_names, temp_dir_path)
-        cleanInstanceImport(instance_ipath, product_file_names, temp_dir_path)
-    else:
-        print >> import_out, "!!! Failure importing: there is no file for importing to be found."
-    result = import_out
-    del globals()['import_out']
-    return result.getvalue()
-
-######################################################################
-##              INSTALLATION/UNINSTALLATION UTILS                   ##
-######################################################################
-CSS_REG_PROPS = ['id', 'expression', 'enabled', 'cookable', 'cacheable' \
-                ,'media', 'rel', 'title', 'rendering', 'compression']
-JS_REG_PROPS = ['id', 'expression', 'enabled', 'cookable', 'cacheable' \
-               ,'inline', 'compression']
-
-def installSkin(portal, pp_up, out):
-    # Checking for presense SKIN_NAME in portal_skins directory view or among Skin Names
-    skinsTool = getToolByName(portal, 'portal_skins')
-    # Get unique product_skin_name and remember it in case of differ from SKIN_NAME.
-    product_skin_name = SKIN_NAME
-    skin_names = skinsTool.getSkinSelections()
-    if product_skin_name in skin_names:
-        idx = 0
-        while product_skin_name in skin_names:
-            product_skin_name = SKIN_NAME + str(idx)
-            idx += 1
-        addProperty(pp_up, 'q_actual_skin_name', product_skin_name, 'string', out)
-    # Add directory views
-    layer_skin_name = string.lower(SKIN_NAME)
-    addDirectoryViews(skinsTool, 'skins', GLOBALS)
-    print >> out,  "- added '%%s' directory views to portal_skins." %% layer_skin_name
-    # Get Default skin and remember it for backup on uninstallig
-    default_skin = skinsTool.getDefaultSkin()
-    addProperty(pp_up, 'q_default_skin', default_skin, 'string', out)
-    # Building list of layers for NEW SKIN
-    base_path = skinsTool.getSkinPath(BASE_SKIN_NAME)
-    new_path = map( string.strip, string.split(base_path,',') )
-    if layer_skin_name in new_path :
-        print >> out, "- %%s layer already present in '%%s' skin." %% (layer_skin_name, BASE_SKIN_NAME)
-        # Remove layer_skin_name from current position.
-        del new_path[new_path.index(layer_skin_name)]
-    # Add layer_skin_name just after 'custom' position
-    try: 
-        new_path.insert(new_path.index('custom')+1, layer_skin_name)
-    except ValueError:
-        new_path.append(layer_skin_name)
-    new_path = string.join(new_path, ', ')
-    # Add NEW Skin and set it as dafault
-    skinsTool.addSkinSelection(product_skin_name, new_path, make_default=1)
-    print >> out, "Added %%s skin, bassed on %%s and set as default." %% (product_skin_name, BASE_SKIN_NAME)
-
-def uninstallSkin(skinsTool, actual_skin_name, initial_skin):
-    # Get 'portal_skins' object and list available skin names
-    # And remove SKIN_NAME from available skins, if it present
-    skin_names = skinsTool.getSkinSelections()
-    if actual_skin_name in skin_names :
-        skinsTool.manage_skinLayers(chosen=(actual_skin_name,), del_skin=1, REQUEST=None)
-        skin_names.remove(actual_skin_name)
-    # Remove product skin directory from skins tool 
-    # AND Remove skin-product layer from available skins
-    skin_layer = SKIN_NAME.lower()
-    if skin_layer in skinsTool.objectIds():
-        skinsTool.manage_delObjects(skin_layer)
-    for skin_name in skin_names:
-        path = skinsTool.getSkinPath(skin_name)
-        path = [i.strip() for i in  path.split(',')]
-        if skin_layer in path:
-            path.remove(skin_layer)
-            path = ','.join(path)
-            skinsTool.addSkinSelection(skin_name, path)
-    # If current default skin == actual_skin_name
-    # Set default skin in initial one (if initial skin still exist) 
-    # or in 1st from available skin names list.
-    current_default_skin = skinsTool.getDefaultSkin()
-    if current_default_skin == actual_skin_name:
-        if initial_skin in skin_names :
-            skinsTool.manage_properties(default_skin=initial_skin, REQUEST=None)
-        elif len(skin_names)>0 :
-            skinsTool.manage_properties(default_skin=skin_names[0], REQUEST=None)
-
-def addProperty(p_sheet, p_id, p_value, p_type, out):
-    if p_sheet.hasProperty(p_id):
-        p_sheet._delProperty(p_id)
-    p_sheet._setProperty(p_id, p_value, p_type)
-    print >> out, "... added %%s PropertySheet to %%s." %% (p_id, p_sheet.getId())
-
-def getResourceProperties(obj, prop_list, dflt=''):
-    """ Return list of 2 items list-[property name, property value]."""
-    properties=[]
-    for prop in prop_list:
-        accessor = getattr(obj, 'get%%s' %% prop.capitalize(), None)
-        if accessor:
-            properties.append([prop, accessor() or dflt])
-    return properties
-
-def registerResource(pp_up, portal_res, resRegisterFunction, out \
-                    ,RESOURCE_SKIN_LIST, SKIN_RES_REGDATA, UP_PROPERTY, RES_REG_PROPS):
-    """ Register resources in portal's registry, remember existant settings."""
-    # Get original registered resources
-    portal_res_srings = []
-    for r in portal_res.getResources():
-        portal_res_srings.append(";".join(['%%s::%%s'%%(r[0],str(r[1])) \
-                                for r in getResourceProperties(r, RES_REG_PROPS)]))
-    addProperty(pp_up, UP_PROPERTY, portal_res_srings, 'lines', out)
-    # Tune Resource registry according to new skin needs
-    unexistent = [] # list of default resources, 
-                    # which present in Skin-product, BUT absent in portal
-    portal_res_ids = portal_res.getResourceIds()
-    for res_dict in SKIN_RES_REGDATA:
-        if res_dict['id'] not in portal_res_ids:
-            # It's interesting - Resource Registry allow adding unexistent resource - use this
-            resRegisterFunction(**res_dict)
-            if res_dict['id'] not in RESOURCE_SKIN_LIST:
-                unexistent.append(res_dict['id'])
-        else:
-            pos = portal_res.getResourcePosition(res_dict['id'])
-            portal_res.unregisterResource(res_dict['id'])
-            resRegisterFunction(**res_dict)
-            portal_res.moveResource(res_dict['id'], pos)
-    if unexistent:
-        print >> out, "!!! - BAD: your Resource Regestry have'nt %%s resource(s), which may lead to some problems." %% unexistent
-
-def getVersion(res_list):
-    """Check version of skin product generator."""
-    return (res_list and not '::' in res_list[0] and '0.5') or '0.7'
-
-def uninstallResource(portal_res, original_res_list, RESOURCE_SKIN_LIST, resRegisterFunction):
-    # Prepare Resource Registry data for backup to original state
-    original_res_regestry = {}
-    genVersion = getVersion(original_res_list)
-    for rec in original_res_list:
-        resource = {}
-        if genVersion == '0.7':
-            [resource.update({prop.split('::')[0]:prop.split('::')[1]}) for prop in rec.split(";")]
-        elif genVersion == '0.5':
-            props = rec.split(";")
-            [resource.update({CSS_BASE_IDS_QPSD053[i]:props[i]}) for i in range(len(CSS_BASE_IDS_QPSD053))]
-        original_res_regestry[resource.pop('id')] = resource
-    # Work up actual Resource Registry
-    res_dict = portal_res.getResourcesDict()
-    for res_id in res_dict.keys():
-        # Remove from Resource Registry Skin product's resources
-        if res_id in RESOURCE_SKIN_LIST \
-           and res_id not in original_res_regestry.keys():
-            portal_res.unregisterResource(res_id)
-            continue
-        # Backup 'enabled' property Registry's resourses to it's original state
-        if original_res_regestry.has_key(res_id):
-            act_Enabled_state = res_dict[res_id].getEnabled()
-            orig_Enabled_state = original_res_regestry[res_id]['enabled']
-            if act_Enabled_state != orig_Enabled_state:
-                pos = portal_res.getResourcePosition(res_id)
-                resource = res_dict[res_id]
-                res = original_res_regestry[res_id]
-                portal_res.unregisterResource(res_id)
-                resRegisterFunction(res_id, **res)
-                portal_res.moveResource(res_id, pos)
-
-def customizeSlots(portal, pp_up, out):
-    # Get original Site's column lists
-    orig_left_slots = left_column = list(portal.left_slots)
-    orig_right_slots = right_column = list(portal.right_slots)
-    # Save original Site's LEFT and RIGHT slots
-    addProperty(pp_up, 'q_left_slots', orig_left_slots, 'lines', out)
-    addProperty(pp_up, 'q_right_slots', orig_right_slots, 'lines', out)
-    # blend-with-site - to portal's slots adding only new one from skin-porduct
-    # blend-with-skin - portal slots forming in the following manner: 
-    #                   first adding skin-porduct's slots, than new one from portal
-    # replace - to portal's slots forming only from the skin-porduct's slot list
-    if SLOT_FORMING == "blend_with_skin":
-        left_column, right_column = formSlotsColumn(LEFT_SLOTS, RIGHT_SLOTS, 
-                                                    orig_left_slots, orig_right_slots, MAIN_COLUMN)
-    elif SLOT_FORMING == "blend_with_site":
-        left_column, right_column = formSlotsColumn(orig_left_slots, orig_right_slots,
-                                                    LEFT_SLOTS, RIGHT_SLOTS, MAIN_COLUMN )
-    elif SLOT_FORMING == "replace":
-        left_column, right_column = formSlotsColumn(LEFT_SLOTS, RIGHT_SLOTS, [], [], MAIN_COLUMN)
-    # REPLACE SITE's column slots
-    portal.left_slots = tuple(left_column)
-    portal.right_slots = tuple(right_column)
-    print >> out, "Complited portal slots customization ..."
-
-# main_column ("left" / "right" / "both") mean which of the MAIN column is favour
-def formSlotsColumn(main_left, main_right, slave_left=[], slave_right=[], main_column="both"):
-    result_left = main_left
-    result_right = main_right
-    if main_column == "left":
-    # 1) APPEND to MAIN_LEFT list *new for main_left column* slots from slave_left list 
-    # 2) APPEND to MAIN_RIGHT list *new for both main columns* slots from slave_right
-    # 3) REMOVE slots from MAIN_RIGHT list, which are *doubled* in MAIN_LEFT
-        [result_left.append(slot) for slot in slave_left if slot not in result_left]
-        [result_right.append(slot) for slot in slave_right \
-                                   if slot not in result_right and slot not in result_left]
-        [result_right.remove(slot) for slot in result_left if slot in result_right]
-    elif main_column == "right":
-    # 1) APPEND to MAIN_LEFT list *new for main_right column* slots from slave_left list 
-    # 2) APPEND to MAIN_RIGHT list *new for both main columns* slots from slave_right
-    # 3) REMOVE slots from MAIN_LEFT list, which are *doubled* in MAIN_RIGHT
-        [result_right.append(slot) for slot in slave_right if slot not in result_right]
-        [result_left.append(slot) for slot in slave_left \
-                                  if slot not in result_left and slot not in result_right]
-        [result_left.remove(slot) for slot in result_right if slot in result_left]
-    elif main_column == "both":
-    # 1) APPEND to MAIN_LEFT list *new for both main columns* slots from slave_left list 
-    # 2) APPEND to MAIN_RIGHT list *new for both main columns* slots from slave_right
-        [result_left.append(slot) for slot in slave_left \
-                                  if slot not in result_left and slot not in result_right]
-        [result_right.append(slot) for slot in slave_right \
-                                   if slot not in result_right and slot not in result_left]
-    return [result_left, result_right]
-
-def getProperty(pp, ps, id, default=[]):
-    """ Get property from portal_properties/[property_sheet]"""
-    res = default
-    if ps in pp.objectIds() and pp[ps].hasProperty(id):
-        res = pp[ps].getProperty(id, default)
-    return res
Index: qPloneSkinDump/trunk/skin_template/HISTORY.txt
===================================================================
--- qPloneSkinDump/trunk/skin_template/HISTORY.txt	(revision 74)
+++ qPloneSkinDump/trunk/skin_template/HISTORY.txt	(revision 74)
@@ -0,0 +1,5 @@
+%(SKIN_PRODUCT_NAME)s Change Log
+
+  %(creation_date)s - 0.1 Release
+
+    - Initial version for plone 3;
Index: qPloneSkinDump/trunk/skin_template/VERSION.txt
===================================================================
--- qPloneSkinDump/trunk/skin_template/VERSION.txt	(revision 74)
+++ qPloneSkinDump/trunk/skin_template/VERSION.txt	(revision 74)
@@ -0,0 +1,1 @@
+0.1
Index: qPloneSkinDump/trunk/skin_template/__init__.py
===================================================================
--- qPloneSkinDump/trunk/skin_template/__init__.py	(revision 1)
+++ qPloneSkinDump/trunk/skin_template/__init__.py	(revision 74)
@@ -1,4 +1,1 @@
-from Products.CMFCore.DirectoryView import registerDirectory
-from config import GLOBALS
-
-registerDirectory('skins', GLOBALS)
+#
Index: qPloneSkinDump/trunk/skin_template/browser/__init__.py
===================================================================
--- qPloneSkinDump/trunk/skin_template/browser/__init__.py	(revision 74)
+++ qPloneSkinDump/trunk/skin_template/browser/__init__.py	(revision 74)
@@ -0,0 +1,1 @@
+#
Index: qPloneSkinDump/trunk/skin_template/browser/configure.zcml
===================================================================
--- qPloneSkinDump/trunk/skin_template/browser/configure.zcml	(revision 74)
+++ qPloneSkinDump/trunk/skin_template/browser/configure.zcml	(revision 74)
@@ -0,0 +1,14 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:browser="http://namespaces.zope.org/browser"
+    i18n_domain="custom_i18n_domain">
+
+    <interface
+        interface=".interfaces.ITheme%(skin_name_capital)s"
+        type="zope.publisher.interfaces.browser.IBrowserSkinType"
+        name="%(skin_name)s"
+        />
+
+    <include file="viewlets.zcml"/>
+
+</configure>
Index: qPloneSkinDump/trunk/skin_template/browser/interfaces.py
===================================================================
--- qPloneSkinDump/trunk/skin_template/browser/interfaces.py	(revision 74)
+++ qPloneSkinDump/trunk/skin_template/browser/interfaces.py	(revision 74)
@@ -0,0 +1,5 @@
+from plone.theme.interfaces import IDefaultPloneLayer
+
+class ITheme%(skin_name_capital)s(IDefaultPloneLayer):
+    """Marker interface that defines a Zope 3 skin layer.
+    """
Index: qPloneSkinDump/trunk/skin_template/browser/viewlets.zcml
===================================================================
--- qPloneSkinDump/trunk/skin_template/browser/viewlets.zcml	(revision 74)
+++ qPloneSkinDump/trunk/skin_template/browser/viewlets.zcml	(revision 74)
@@ -0,0 +1,8 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:browser="http://namespaces.zope.org/browser"
+    i18n_domain="custom_i18n_domain">
+
+    %(viewlets_zcml)s
+
+</configure>
Index: qPloneSkinDump/trunk/skin_template/config.py
===================================================================
--- qPloneSkinDump/trunk/skin_template/config.py	(revision 1)
+++ qPloneSkinDump/trunk/skin_template/config.py	(revision 74)
@@ -1,2 +1,3 @@
+import os
 ## PLONE AND SKIN PRODUCT SPECIFIC CONSTANTS
 GLOBALS = globals()
@@ -14,6 +15,6 @@
 ## ['some/portlet1','some/portlet2'] - will change appropriate (left or right)
 ##                                     slot to listed portlets
-LEFT_SLOTS = %(LEFT_SLOTS)s
-RIGHT_SLOTS = %(RIGHT_SLOTS)s
+#LEFT_SLOTS = %(LEFT_SLOTS)s
+#RIGHT_SLOTS = %(RIGHT_SLOTS)s
 
 ## Slot's list forming procedure.
@@ -24,5 +25,5 @@
 #SLOT_FORMING = "blend_with_site"
 #SLOT_FORMING = "replace"
-SLOT_FORMING = "%(SLOT_FORMING)s"
+#SLOT_FORMING = "%(SLOT_FORMING)s"
 
 ## Favour column for slots forming procedure. IMPORTANT only for 'Blend with...' 
@@ -37,5 +38,5 @@
 #MAIN_COLUMN = "right"
 #MAIN_COLUMN = "both"
-MAIN_COLUMN = "%(MAIN_COLUMN)s"
+#MAIN_COLUMN = "%(MAIN_COLUMN)s"
 
 
@@ -100,2 +101,17 @@
 from Products.CMFCore.utils import getToolByName
 FINAL_CUSTOMIZATION_FUNCTIONS = []
+
+# site portlets registry
+SLOT_STRUCTURE = %(slot_structure)s
+
+# portal_view_customization content
+CUSTOM_VIEWS = %(custom_views)s
+
+# absolute file system path to product
+from Globals import package_home
+PRODUCTS_PATH = os.sep.join(package_home(GLOBALS).split(os.sep)[:-1])
+
+## GenericSetup constants
+GS_INSTALL_PROFILE      = "profile-Products.%(product_name)s:default"
+GS_AFTERINSTALL_PROFILE = "profile-Products.%(product_name)s:afterinstall"
+GS_UNINSTALL_PROFILE    = "profile-Products.%(product_name)s:uninstall"
Index: qPloneSkinDump/trunk/skin_template/configure.zcml
===================================================================
--- qPloneSkinDump/trunk/skin_template/configure.zcml	(revision 74)
+++ qPloneSkinDump/trunk/skin_template/configure.zcml	(revision 74)
@@ -0,0 +1,12 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:cmf="http://namespaces.zope.org/cmf"
+    i18n_domain="%(product_name_lowercase)s">
+
+ <include file="profiles.zcml" />
+
+ <include file="skins.zcml" />
+
+ <include package=".browser" />
+
+</configure>
Index: qPloneSkinDump/trunk/skin_template/fixes.py
===================================================================
--- qPloneSkinDump/trunk/skin_template/fixes.py	(revision 74)
+++ qPloneSkinDump/trunk/skin_template/fixes.py	(revision 74)
@@ -0,0 +1,55 @@
+from Acquisition import aq_base
+from Products.CMFCore.utils import getToolByName
+from Products.ZCatalog.ProgressHandler import ZLogHandler
+from plone.app.linkintegrity.handlers import referencedRelationship as li_relation
+
+portal_catalog = None
+portal_repository = None
+uid_catalog = None
+reference_catalog = None
+
+def fix_archivest(ob):
+    ''' Fix #7334 bug of CMFEdition.
+        Fixed in CMFEdition v1.1.5+
+    '''
+    if portal_repository.isVersionable(ob):
+        portal_repository.save(obj=ob, comment="")
+
+def fix_catalog(ob):
+    ob.reindexObject()
+
+def fix_linkintegrity(ob):
+    """Fix losed references."""
+    uobject = aq_base(ob)
+    if reference_catalog.isReferenceable(uobject):
+        ob_li_refs = reference_catalog.getReferences(ob, relationship=li_relation)
+        if ob_li_refs:
+            annotations = ob._getReferenceAnnotations()
+            uniqueUIDs = uid_catalog.uniqueValuesFor('UID')
+            # delete references to non-existent objects
+            [annotations._delObject(ref.id) for ref in ob_li_refs \
+             if not ref.targetUID in uniqueUIDs]
+        
+def fix_all(ob):
+    """ Recursive function for perform registered
+        actions for all internal objects
+    """
+    [a(ob) for a in perobject_actions]
+
+    if getattr(ob, 'is_folderish', None):
+        [fix_all(o) for o in ob.objectValues()]
+
+perobject_actions = [fix_archivest, fix_catalog, fix_linkintegrity]
+
+def fix(context):
+    ''' Main fix function: fix defects of importing:
+        imported objects - absence in catalogs, some other issues'''
+    global portal_repository, portal_catalog
+    global uid_catalog, reference_catalog
+    portal_catalog = getToolByName(context,'portal_catalog')
+    portal_repository = getToolByName(context,'portal_repository')
+    uid_catalog = getToolByName(context,'uid_catalog')
+    reference_catalog = getToolByName(context,'reference_catalog')
+
+    fix_all(context)
+
Index: qPloneSkinDump/trunk/skin_template/profiles.zcml
===================================================================
--- qPloneSkinDump/trunk/skin_template/profiles.zcml	(revision 74)
+++ qPloneSkinDump/trunk/skin_template/profiles.zcml	(revision 74)
@@ -0,0 +1,30 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:genericsetup="http://namespaces.zope.org/genericsetup"
+    i18n_domain="%(product_name_lowercase)s">
+
+  <genericsetup:registerProfile
+      name="default"
+      title="%(product_name)s"
+      directory="profiles/default"
+      description="Extension profile for %(product_name)s."
+      provides="Products.GenericSetup.interfaces.EXTENSION"
+      />
+
+  <genericsetup:registerProfile
+      name="afterinstall"
+      title="%(product_name)s:afterinstall"
+      directory="profiles/afterinstall"
+      description="Extension profile for install zexps and other dependent objects of %(product_name)s."
+      provides="Products.GenericSetup.interfaces.EXTENSION"
+      />
+
+  <genericsetup:registerProfile
+      name="uninstall"
+      title="%(product_name)s:uninstall"
+      directory="profiles/uninstall"
+      description="Extension profile for UNINSTALL %(product_name)s."
+      provides="Products.GenericSetup.interfaces.EXTENSION"
+      />
+
+</configure>
Index: qPloneSkinDump/trunk/skin_template/profiles/afterinstall/import_steps.xml
===================================================================
--- qPloneSkinDump/trunk/skin_template/profiles/afterinstall/import_steps.xml	(revision 74)
+++ qPloneSkinDump/trunk/skin_template/profiles/afterinstall/import_steps.xml	(revision 74)
@@ -0,0 +1,29 @@
+<?xml version="1.0"?>
+<import-steps>
+ <import-step id="%(skin_name)s_zexps" version="%(version)s-1"
+              handler="Products.%(product_name)s.setuphandlers.importZexps"
+              title="Import zexp objects">
+   Import zexp objects
+ </import-step>
+ <import-step id="%(skin_name)s_customviews" version="%(version)s-2"
+              handler="Products.%(product_name)s.setuphandlers.importCustomViews"
+              title="Import customized views">
+  <dependency step="%(skin_name)s_zexps"/>
+   Import customized views to portal_view_customizations.
+ </import-step>
+ <import-step id="%(skin_name)s_portlets" version="%(version)s-3"
+              handler="Products.%(product_name)s.setuphandlers.importPortlets"
+              title="Customize %(skin_name)s portlets">
+  <dependency step="%(skin_name)s_zexps"/>
+  <dependency step="%(skin_name)s_customviews"/>
+   Customize %(skin_name)s left and right portlets.
+ </import-step>
+ <import-step id="%(skin_name)s_various" version="%(version)s-4"
+              handler="Products.%(product_name)s.setuphandlers.importVarious"
+              title="Perform various skin customizations">
+  <dependency step="%(skin_name)s_portlets"/>
+  <dependency step="%(skin_name)s_customviews"/>
+  <dependency step="%(skin_name)s_zexps"/>
+   Perform various skin product final customizations.
+ </import-step>
+</import-steps>
Index: qPloneSkinDump/trunk/skin_template/profiles/default/cssregistry.xml
===================================================================
--- qPloneSkinDump/trunk/skin_template/profiles/default/cssregistry.xml	(revision 74)
+++ qPloneSkinDump/trunk/skin_template/profiles/default/cssregistry.xml	(revision 74)
@@ -0,0 +1,1 @@
+%(stylesheets_xml)s
Index: qPloneSkinDump/trunk/skin_template/profiles/default/jsregistry.xml
===================================================================
--- qPloneSkinDump/trunk/skin_template/profiles/default/jsregistry.xml	(revision 74)
+++ qPloneSkinDump/trunk/skin_template/profiles/default/jsregistry.xml	(revision 74)
@@ -0,0 +1,1 @@
+%(javascripts_xml)s
Index: qPloneSkinDump/trunk/skin_template/profiles/default/propertiestool.xml
===================================================================
--- qPloneSkinDump/trunk/skin_template/profiles/default/propertiestool.xml	(revision 74)
+++ qPloneSkinDump/trunk/skin_template/profiles/default/propertiestool.xml	(revision 74)
@@ -0,0 +1,7 @@
+<?xml version="1.0"?>
+<object name="portal_properties" meta_type="Plone Properties Tool">
+ <object name="%(product_name_lowercase)s_properties" meta_type="Plone Property Sheet">
+  <property name="title">%(product_name)s properties</property>
+  <property name="portlets_before_install" type="string">[]</property>
+ </object>
+</object>
Index: qPloneSkinDump/trunk/skin_template/profiles/default/skins.xml
===================================================================
--- qPloneSkinDump/trunk/skin_template/profiles/default/skins.xml	(revision 74)
+++ qPloneSkinDump/trunk/skin_template/profiles/default/skins.xml	(revision 74)
@@ -0,0 +1,9 @@
+<?xml version="1.0"?>
+<object name="portal_skins" meta_type="Plone Skins Tool" allow_any="False"
+   cookie_persistence="False" default_skin="%(skin_name)s"
+   request_varname="plone_skin">
+%(directory_views_xml)s
+ <skin-path name="%(skin_name)s">
+%(skin_layers)s
+ </skin-path>
+</object>
Index: qPloneSkinDump/trunk/skin_template/profiles/uninstall/import_steps.xml
===================================================================
--- qPloneSkinDump/trunk/skin_template/profiles/uninstall/import_steps.xml	(revision 74)
+++ qPloneSkinDump/trunk/skin_template/profiles/uninstall/import_steps.xml	(revision 74)
@@ -0,0 +1,14 @@
+<?xml version="1.0"?>
+<import-steps>
+ <import-step id="%(skin_name)s_uninstallPortlets" version="20080312-1"
+              handler="Products.%(product_name)s.uninstallhandlers.uninstallPortlets"
+              title="Uninstall %(product_name)s portlets">
+   Uninstall custom %(product_name)s left and right portlets.
+ </import-step>
+ <import-step id="%(skin_name)s_uninstallProperties" version="20080312-2"
+              handler="Products.%(product_name)s.uninstallhandlers.uninstallProperties"
+              title="Remove %(product_name)s properties">
+  <dependency step="%(skin_name)s_uninstallPortlets"/>
+    Remove %(product_name)s properties.
+ </import-step>
+</import-steps>
Index: qPloneSkinDump/trunk/skin_template/profiles/uninstall/skins.xml
===================================================================
--- qPloneSkinDump/trunk/skin_template/profiles/uninstall/skins.xml	(revision 74)
+++ qPloneSkinDump/trunk/skin_template/profiles/uninstall/skins.xml	(revision 74)
@@ -0,0 +1,5 @@
+<?xml version="1.0"?>
+<object name="portal_skins" default_skin="Plone Default">
+ %(remove_directory_views_xml)s
+ <skin-path name="%(SKIN_NAME)s" remove="True" />
+</object>
Index: qPloneSkinDump/trunk/skin_template/setuphandlers.py
===================================================================
--- qPloneSkinDump/trunk/skin_template/setuphandlers.py	(revision 74)
+++ qPloneSkinDump/trunk/skin_template/setuphandlers.py	(revision 74)
@@ -0,0 +1,179 @@
+import sys
+from logging import getLogger
+
+from BTrees.OOBTree import OOBTree
+from persistent.list import PersistentList
+
+from zope.dottedname.resolve import resolve
+from zope.component import getUtility, getSiteManager, getMultiAdapter
+
+from plone.portlets.interfaces import IPortletAssignmentMapping, IPortletManager, IPlacelessPortletManager
+from plone.portlets.interfaces import IPortletContext, IPortletDataProvider
+from plone.portlets.interfaces import ILocalPortletAssignmentManager
+from plone.portlets.storage import PortletCategoryMapping, PortletAssignmentMapping
+from plone.app.portlets import portlets
+
+from plone.app.customerize.registration import *
+
+from Products.CMFCore.utils import getToolByName
+from Products.GenericSetup.utils import _getDottedName, _resolveDottedName
+
+from Products.%(product_name)s.config import *
+from Products.%(product_name)s.utils import *
+from Products.%(product_name)s.utilsPortlets import dumpPortlets
+
+logger = getLogger('%(product_name)s')
+
+def assignPortlet(mapping, info):
+    name = info['name']
+    try:
+        assignment = _resolveDottedName(info['class'])
+    except:
+        e,v,tr = sys.exc_info()
+        logger.info('Debug from setup portlets handler: %%s: %%s (%%s)' , info['class'], str(v), str(e))
+        return False
+    else:
+        portlet = assignment(**info['kwargs'])
+        if mapping.get(name, None) is not None:
+            del mapping[name]
+        mapping[name] = portlet
+        return portlet
+
+def setupSiteWidePortlets(site, data, managers):
+
+    for name, info in data:
+        manager = managers.get(name, None)
+        if manager is not None:
+            for category, keys in info.items():
+                catmapping = manager.get(category, None)
+                if catmapping is None:
+                    catmapping = manager[category] = PortletCategoryMapping()
+                for key, assignments in keys.items():
+                    mapping = catmapping.get(key, None)
+                    if mapping is None:
+                        mapping = catmapping[key] = PortletAssignmentMapping()
+                    for assignment in assignments.values():
+                        assignPortlet(mapping, assignment)
+
+def setupPortletsForContext(context, data, managers):
+
+    for name, info in data:
+        manager = managers.get(name, None)
+        if manager is not None:
+            # set portlet assignments
+            mapping = getMultiAdapter((context, manager), IPortletAssignmentMapping, context=context)
+
+            # purge mapping
+            mapping._data = OOBTree()
+            mapping._order = PersistentList()
+
+            if info['assignments']:
+                # set portlet assignments
+                for assignment in info['assignments']:
+                    assignPortlet(mapping, assignment)
+            if info['blacklists']:
+                # set blacklists
+                localassignmentmanager = getMultiAdapter((context, manager), ILocalPortletAssignmentManager, context=context)
+                for category, status in info['blacklists']:
+                    localassignmentmanager.setBlacklistStatus(category, status)
+
+
+def saveBeforeInstallPortlets(context):
+    # Save information about portlets before installation
+
+    beforeInstall = dumpPortlets(context=context, dump_policy='root', dump_portlets_selection=[] )
+
+    # update properties list
+    pp = getToolByName(context, 'portal_properties')
+    skin_props = pp._getOb('%(product_name_lowercase)s_properties')
+    skin_props._updateProperty('portlets_before_install', str(beforeInstall) )
+
+
+def importPortlets(context):
+
+    if context.readDataFile("%(afterinstall_profile_marker)s") is None:
+        return
+
+    site = context.getSite()
+
+    saveBeforeInstallPortlets(site)
+
+    components = getSiteManager(site)
+    ms = [r for r in components.registeredUtilities() if r.provided.isOrExtends(IPortletManager)]
+    context_managers = {}
+    for m in ms:
+        if not m.provided.isOrExtends(IPlacelessPortletManager):
+            context_managers[m.name] = getUtility(IPortletManager, name=m.name, context=site)
+
+    managers = {}
+    for m in ms:
+        managers[m.name] = getUtility(IPortletManager, name=m.name, context=site)
+
+    for path, info in SLOT_STRUCTURE:
+        if path == '__site-wide-portlets__':
+            setupSiteWidePortlets(site, info, managers)
+        else:
+            try:
+                obj = site.restrictedTraverse(path)
+            except:
+                e,v,tr = sys.exc_info()
+                logger.info('Debug from importPortlets handler: %%s: %%s (%%s)' , path, str(v), str(e))
+            else:
+                setupPortletsForContext(obj, info, context_managers)
+
+def importZexps(context):
+
+    if context.readDataFile("%(afterinstall_profile_marker)s") is None:
+        return
+
+    site = context.getSite()
+    if checkIfImport():
+        performImportToPortal(site)
+
+def importVarious(context):
+
+    if context.readDataFile("%(afterinstall_profile_marker)s") is None:
+        return
+
+    site = context.getSite()
+    out = StringIO()
+    if FINAL_CUSTOMIZATION_FUNCTIONS:
+        dummy = [func(site, out) for func in FINAL_CUSTOMIZATION_FUNCTIONS]
+
+def importCustomViews(context):
+
+    if context.readDataFile("%(afterinstall_profile_marker)s") is None:
+        return
+
+    site = context.getSite()
+
+    for view in CUSTOM_VIEWS:
+        for_name = view['for_name']
+        view_name = view['view_name']
+        type_name = view['type_name']
+        kwargs = view['kwargs']
+
+        reg = findTemplateViewRegistration(for_name, type_name, view_name)
+        viewzpt_id = str(generateIdFromRegistration(reg))
+
+        container = getUtility(IViewTemplateContainer)
+        if viewzpt_id in container.objectIds():
+            continue
+
+        attr, pt = findViewletTemplate(reg.factory)
+        if pt:
+            ptname = basename(pt.filename)
+        else:
+            ptname = None
+        viewzpt = TTWViewTemplate(
+            id = viewzpt_id,
+            text = kwargs['text'],
+            encoding = kwargs['encoding'],
+            content_type = kwargs['content_type'],
+            view = getViewClassFromRegistration(reg),
+            permission = getViewPermissionFromRegistration(reg),
+            name = ptname)
+        container.addTemplate(viewzpt_id, viewzpt)
+
+        sm = getSiteManager(site)
+        sm.registerAdapter(viewzpt, required = reg.required, provided = reg.provided, name = reg.name)
Index: qPloneSkinDump/trunk/skin_template/skins.zcml
===================================================================
--- qPloneSkinDump/trunk/skin_template/skins.zcml	(revision 74)
+++ qPloneSkinDump/trunk/skin_template/skins.zcml	(revision 74)
@@ -0,0 +1,8 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:cmf="http://namespaces.zope.org/cmf"
+    i18n_domain="%(product_name_lowercase)s">
+
+   <cmf:registerDirectory name="skins" directory="skins" recursive="True" />
+
+</configure>
Index: qPloneSkinDump/trunk/skin_template/uninstallhandlers.py
===================================================================
--- qPloneSkinDump/trunk/skin_template/uninstallhandlers.py	(revision 74)
+++ qPloneSkinDump/trunk/skin_template/uninstallhandlers.py	(revision 74)
@@ -0,0 +1,72 @@
+from zope.dottedname.resolve import resolve
+from zope.component import getUtility, getSiteManager, getMultiAdapter
+
+from plone.portlets.interfaces import IPortletAssignmentMapping, IPortletManager, IPlacelessPortletManager
+from plone.portlets.interfaces import IPortletContext, IPortletDataProvider
+from plone.portlets.interfaces import ILocalPortletAssignmentManager
+from plone.portlets.storage import PortletCategoryMapping, PortletAssignmentMapping
+from plone.app.portlets import portlets
+
+from plone.app.customerize.registration import *
+
+from Products.CMFCore.utils import getToolByName
+from Products.GenericSetup.utils import _getDottedName, _resolveDottedName
+
+from Products.%(product_name)s.config import *
+from Products.%(product_name)s.utils import *
+from Products.%(product_name)s.setuphandlers import setupSiteWidePortlets
+from Products.%(product_name)s.setuphandlers import setupPortletsForContext
+
+import sys
+from logging import getLogger
+logger = getLogger('%(product_name)s:unistall')
+
+_marker = []
+
+
+def uninstallPortlets(context):
+    if context.readDataFile('%(uninstall_profile_marker)s') is None:
+        return
+
+    site = context.getSite()
+
+    components = getSiteManager(site)
+    ms = [r for r in components.registeredUtilities() if r.provided.isOrExtends(IPortletManager)]
+    context_managers = {}
+    for m in ms:
+        if not m.provided.isOrExtends(IPlacelessPortletManager):
+            context_managers[m.name] = getUtility(IPortletManager, name=m.name, context=site)
+
+    managers = {}
+    for m in ms:
+        managers[m.name] = getUtility(IPortletManager, name=m.name, context=site)
+
+    # initiate list for collect blacklist properties
+    pp = getToolByName(site, 'portal_properties')
+    estate_props = getattr(pp, '%(product_name_lowercase)s_properties', None)
+    slots_structure_before_install = estate_props.getProperty('portlets_before_install',"[]")
+    slots_info = eval(slots_structure_before_install)
+
+    for path, info in slots_info:
+        if path == '__site-wide-portlets__':
+            setupSiteWidePortlets(site, info, managers)
+        else:
+            try:
+                obj = site.restrictedTraverse(path)
+            except:
+                e,v,tr = sys.exc_info()
+                logger.info('Debug from importPortlets handler: %%s: %%s (%%s)' , path, str(v), str(e))
+            else:
+                setupPortletsForContext(obj, info, context_managers)
+
+
+def uninstallProperties(context):
+    if context.readDataFile('%(uninstall_profile_marker)s') is None:
+        return
+
+    site = context.getSite()
+    portal_properties = getToolByName(site, 'portal_properties')
+    
+    if '%(product_name_lowercase)s_properties' in portal_properties.objectIds():
+           portal_properties.manage_delObjects(ids=['%(product_name_lowercase)s_properties',])
+
Index: qPloneSkinDump/trunk/skin_template/utils.py
===================================================================
--- qPloneSkinDump/trunk/skin_template/utils.py	(revision 74)
+++ qPloneSkinDump/trunk/skin_template/utils.py	(revision 74)
@@ -0,0 +1,472 @@
+import transaction
+import os, sys, re, string
+from sets import Set
+from StringIO import StringIO
+from time import gmtime, strftime
+from zLOG import LOG, INFO
+from zExceptions import BadRequest
+from App.config import getConfiguration
+from Products.CMFCore.utils import getToolByName
+from Products.CMFCore.DirectoryView import addDirectoryViews
+from Products.%(SKIN_PRODUCT_NAME)s.config import *
+from fixes import fix
+
+######################################################################
+##                      IMPORTING UTILS                             ##
+######################################################################
+osp = os.path
+ALLOWED_IMPORT_POLICY = ["only_new", "backup", "overwrite"]
+INTRO_TO_INSTANCE = "< Started copying object files from Product import directory to Instance one."
+SUMMARY_TO_INSTANCE = "> Finished copying."
+INTRO_TO_ROOT = "< Started import %%s file[s] with '%%s' policy."
+SUMMARY_TO_ROOT = "> Finished importing."
+INTRO_CLEAN = "< Started cleaning Instance import directory."
+SUMMARY_CLEAN = "> Finished cleaning."
+CREXP_INVALID_ID = re.compile('^The id \"(.*?)\" is invalid - it is already in use.$', re.DOTALL|re.IGNORECASE|re.MULTILINE)
+CSS_BASE_IDS_QPSD053 = ['id','expression','enabled','cookable','media','rel','title','rendering']   # supporting qPSD-0.5.3 version
+################    CHECK IMPORTING    ################
+def checkIfImport():
+    """ Return if perform importing, based on checking 
+        *zexp files in <SkinProduct>/import directory.
+    """
+    instance_ipath, product_ipath = getImportedPathes()
+    product_ilist = [i for i in os.listdir(product_ipath) \
+                     if osp.isfile(osp.join(product_ipath,i)) and i.endswith('.zexp')]
+    if product_ilist:
+        return 1
+    return 0
+
+################    IMPORTING TO PLONE'S IMPORT DIR   ################
+def getImportedPathes():
+    """ Return Plone instance and Skin product import pathes."""
+    # Based on instance path, construct import pathes 
+    cfg = getConfiguration()
+    instance_ipath = osp.join(cfg.instancehome, "import")
+    product_ipath = osp.join(PRODUCTS_PATH, PRODUCT_NAME, "import")
+    # Check presence of Product import directory
+    if not osp.isdir(product_ipath):        
+        raise BadRequest, "Skin Product's import directory '%%s' - does not exist or is'nt direcory" %% product_ipath
+    # Check presence of Instance import directory
+    if not osp.isdir(instance_ipath):
+        raise BadRequest, "Instance import directory '%%s' - does not exist or isn't direcory" %% instance_ipath
+    return [instance_ipath, product_ipath]
+
+def copyFile(src_dir, dst_dir, f_name):
+    """ Copy file from src_dir to dst_dir under original name."""
+    try:
+        src_file = open(osp.join(src_dir, f_name),"rb")
+        dst_file = open(osp.join(dst_dir, f_name),"wb")
+        dst_file.write(src_file.read())
+        dst_file.close()
+        src_file.close()
+    except Exception, e:
+        msg = "!!! In copying files from <%%s> dir to <%%s> dir exception occur. Details: %%s." %% (src_dir,dst_dir, str(e))
+        print >> import_out, msg
+        LOG('performImportToPortal',INFO,'copyFile', msg)
+
+def moveToTemp(same_instance_files, instance_ipath, temp_dir_path):
+    """ Move samenamed files from Instanse's dir to temp dir."""
+    os.mkdir(temp_dir_path) # Create temp back_[date] dir
+    try:
+        [copyFile(instance_ipath, temp_dir_path, f_name) for f_name in same_instance_files]
+        [os.remove(osp.join(instance_ipath, f_name)) for f_name in same_instance_files]
+    except Exception, e:
+        msg = "!!! Exception occur during moving files from Instance's dir to temp dir. Detaile:%%s." %% str(e)
+        print >> import_out, msg
+        LOG('performImportToPortal',INFO,'moveToTemp', msg)
+    
+def copyToInstanceImport():
+    """ Perform copying imported files from <SkinProduct>/import dir
+        to Plone's instance import dir.
+    """
+    print >> import_out, INTRO_TO_INSTANCE
+    instance_ipath, product_ipath = getImportedPathes()
+    # Compose temp dir back_[date] dir path in Instance import directory
+    temp_dir_id = "back_%%s" %% strftime("%%Y%%m%%d%%H%%M%%S", gmtime())
+    temp_dir_path = osp.join(instance_ipath, temp_dir_id)
+    # Get *.zexp files from Skin Product's import dir and Plone's instance import dir files
+    product_ilist = [i for i in os.listdir(product_ipath) \
+                     if osp.isfile(osp.join(product_ipath,i)) and i.endswith('.zexp')]
+    instance_ilist = [i for i in os.listdir(instance_ipath) \
+                      if osp.isfile(osp.join(instance_ipath,i)) and i.endswith('.zexp')]
+    # Check for presence samenamed files in Instance and Product import directories.
+    same_instance_files = [f_name for f_name in instance_ilist if f_name in product_ilist]
+    if same_instance_files:
+        moveToTemp(same_instance_files, instance_ipath, temp_dir_path)
+    # Copy all *zexp files from Product's import dir to Instance's import dir
+    [copyFile(product_ipath, instance_ipath, f_name) for f_name in product_ilist]
+    print >> import_out, SUMMARY_TO_INSTANCE
+    return [instance_ipath, product_ipath, temp_dir_path, product_ilist]
+
+################    IMPORTING TO PORTAL   ################
+def importObject(portal, file_name):
+    """ Work around old Zope bug in importing."""
+    try:
+        portal.manage_importObject(file_name)
+    except:
+        portal._p_jar = portal.Destination()._p_jar
+        portal.manage_importObject(file_name)
+
+def makeBackUp(portal, portal_objects, temp_dir_path, obj_id):
+    """ Perfom backup same named portal objects in temp folder."""
+    # Get id of temp folder-object
+    durty_path,temp_id = osp.split(temp_dir_path)
+    if not temp_id:
+        durty_path,temp_id = osp.split(durty_path)
+    # Get temp folder-object
+    if temp_id not in portal_objects:
+        portal.invokeFactory('Large Plone Folder', id=temp_id)
+        print >> import_out, "! Created '%%s' backup directory with same-ids " \
+                             "objects from portal root." %% temp_id
+    temp_dir = getattr(portal, temp_id)
+    # Move object with same id to temp folder-object
+    #get_transaction().commit(1)
+    transaction.savepoint()
+    obj = portal.manage_cutObjects(ids=[obj_id])
+    temp_dir.manage_pasteObjects(obj)
+    print >> import_out, "! '%%s' Object moved from portal root to '%%s' backup directory." %% (obj_id, temp_id)
+
+def performImport(portal, temp_dir_path, file_name):
+    """ Importing an object to portal."""
+    portal_objects = portal.objectIds()
+    try:
+        portal.manage_importObject(file_name)
+    except Exception, e:
+        msg = str(e)
+        is_invalid_id = CREXP_INVALID_ID.match(msg)
+        if is_invalid_id:
+            obj_id = is_invalid_id.group(1)
+            if IMPORT_POLICY == "only_new":
+                msg = "! Object with '%%s' id was not importing because it's already exist " \
+                      "in portal root." %% obj_id
+                print >> import_out, msg
+            elif IMPORT_POLICY == "backup":
+                makeBackUp(portal, portal_objects, temp_dir_path, obj_id)
+                importObject(portal, file_name)
+            elif IMPORT_POLICY == "overwrite":
+                portal.manage_delObjects(ids=[obj_id])
+                importObject(portal, file_name)
+        else:
+            # work around old Zope bug in importing
+            portal._p_jar = portal.Destination()._p_jar
+            portal.manage_importObject(file_name)
+
+def importToPortalRoot(portal, product_file_names, temp_dir_path):
+    """ Import all objects from *zexp files to portal root (based on IMPORT_POLICY)."""
+    if not IMPORT_POLICY in ALLOWED_IMPORT_POLICY:
+        raise Exception("%%s - wrong import policy in '%%s/config.py' file. Must be one of the %%s" \
+                        %% (IMPORT_POLICY, PRODUCT_NAME, ALLOWED_IMPORT_POLICY) )
+    print >> import_out, INTRO_TO_ROOT %% (product_file_names, IMPORT_POLICY)
+    for file_name in product_file_names:
+        try:
+            performImport(portal, temp_dir_path, file_name)
+        except Exception, error:
+            msg = '!!! Under "%%s" policy importing exception occur: %%s.' %% (IMPORT_POLICY, str(error))
+            print >> import_out, msg
+            LOG('performImportToPortal',INFO,'importToPortalRoot', msg)
+    print >> import_out, SUMMARY_TO_ROOT
+
+################    CLEANING PLONE'S IMPORT DIR   ################
+def cleanInstanceImport(instance_ipath, product_file_names, temp_dir_path):
+    """ Cleaning Plone's import dir."""
+    print >> import_out, INTRO_CLEAN
+    # Erase all copied *zexp files from Instance's import dir
+    for f_name in product_file_names:
+        f_path = osp.join(instance_ipath, f_name)
+        if osp.exists(f_path) and osp.isfile(f_path):
+            os.remove(f_path)
+        else:
+            msg = '! "%%s" file was not deleted from "%%s" import directory.' %%\
+                   (f_name, osp.join(instance_ipath))
+            print >> import_out, msg
+            LOG('performImportToPortal',INFO,'cleanInstanceImport', msg)
+    # Move all files from temp back_[date] dir to Instance's import dir
+    if osp.exists(temp_dir_path) and osp.isdir(temp_dir_path):
+        f_names = os.listdir(temp_dir_path)
+        try:
+            [copyFile(temp_dir_path, instance_ipath, f_name) for f_name in f_names]
+            [os.remove(osp.join(temp_dir_path, f_name)) for f_name in f_names]
+            # Erase temp back_[date] dir
+            os.rmdir(temp_dir_path)
+        except Exception, e:
+            msg = "!!! In moving files from temp dir to Instance's import dir exception occur."
+            print >> import_out, msg
+            LOG('performImportToPortal',INFO,'moveFromTempToImport', msg)
+    print >> import_out, SUMMARY_CLEAN
+
+def fixImportingIssues(portal, beforeimporting_objects):
+    ''' Fix defects of importing process: reindexing, other'''
+    afterimporting_objects = portal.objectItems()
+    diff_objects = list(Set(afterimporting_objects)-Set(beforeimporting_objects))
+    for id, ob in diff_objects:
+        if id.startswith('back_'):
+            continue
+        fix(ob)
+
+################    MAIN    ################
+def performImportToPortal(portal):
+    """ Import objects from Skin Product to Portal root."""
+    globals()['import_out'] = StringIO()
+    instance_ipath, product_ipath, temp_dir_path, product_file_names = copyToInstanceImport()
+    if product_file_names:
+        beforeimporting_objects = portal.objectItems()
+        importToPortalRoot(portal, product_file_names, temp_dir_path)
+        fixImportingIssues(portal, beforeimporting_objects)
+        cleanInstanceImport(instance_ipath, product_file_names, temp_dir_path)
+    else:
+        print >> import_out, "!!! Failure importing: there is no file for importing to be found."
+    result = import_out
+    del globals()['import_out']
+    return result.getvalue()
+
+######################################################################
+##              INSTALLATION/UNINSTALLATION UTILS                   ##
+######################################################################
+CSS_REG_PROPS = ['id', 'expression', 'enabled', 'cookable', 'cacheable' \
+                ,'media', 'rel', 'title', 'rendering', 'compression']
+JS_REG_PROPS = ['id', 'expression', 'enabled', 'cookable', 'cacheable' \
+               ,'inline', 'compression']
+
+def installSkin(portal, pp_up, out):
+    # Checking for presense SKIN_NAME in portal_skins directory view or among Skin Names
+    skinsTool = getToolByName(portal, 'portal_skins')
+    # Get unique product_skin_name and remember it in case of differ from SKIN_NAME.
+    product_skin_name = SKIN_NAME
+    skin_names = skinsTool.getSkinSelections()
+    if product_skin_name in skin_names:
+        idx = 0
+        while product_skin_name in skin_names:
+            product_skin_name = SKIN_NAME + str(idx)
+            idx += 1
+        addProperty(pp_up, 'q_actual_skin_name', product_skin_name, 'string', out)
+    # Add directory views
+    layer_skin_name = string.lower(SKIN_NAME)
+    addDirectoryViews(skinsTool, 'skins', GLOBALS)
+    print >> out,  "- added '%%s' directory views to portal_skins." %% layer_skin_name
+    # Get Default skin and remember it for backup on uninstallig
+    default_skin = skinsTool.getDefaultSkin()
+    addProperty(pp_up, 'q_default_skin', default_skin, 'string', out)
+    # Building list of layers for NEW SKIN
+    base_path = skinsTool.getSkinPath(BASE_SKIN_NAME)
+    new_path = map( string.strip, string.split(base_path,',') )
+    if layer_skin_name in new_path :
+        print >> out, "- %%s layer already present in '%%s' skin." %% (layer_skin_name, BASE_SKIN_NAME)
+        # Remove layer_skin_name from current position.
+        del new_path[new_path.index(layer_skin_name)]
+    # Add layer_skin_name just after 'custom' position
+    try: 
+        new_path.insert(new_path.index('custom')+1, layer_skin_name)
+    except ValueError:
+        new_path.append(layer_skin_name)
+    new_path = string.join(new_path, ', ')
+    # Add NEW Skin and set it as dafault
+    skinsTool.addSkinSelection(product_skin_name, new_path, make_default=1)
+    print >> out, "Added %%s skin, bassed on %%s and set as default." %% (product_skin_name, BASE_SKIN_NAME)
+
+def uninstallSkin(skinsTool, actual_skin_name, initial_skin):
+    # Get 'portal_skins' object and list available skin names
+    # And remove SKIN_NAME from available skins, if it present
+    skin_names = skinsTool.getSkinSelections()
+    if actual_skin_name in skin_names :
+        skinsTool.manage_skinLayers(chosen=(actual_skin_name,), del_skin=1, REQUEST=None)
+        skin_names.remove(actual_skin_name)
+    # Remove product skin directory from skins tool 
+    # AND Remove skin-product layer from available skins
+    skin_layer = SKIN_NAME.lower()
+    if skin_layer in skinsTool.objectIds():
+        skinsTool.manage_delObjects(skin_layer)
+    for skin_name in skin_names:
+        path = skinsTool.getSkinPath(skin_name)
+        path = [i.strip() for i in  path.split(',')]
+        if skin_layer in path:
+            path.remove(skin_layer)
+            path = ','.join(path)
+            skinsTool.addSkinSelection(skin_name, path)
+    # If current default skin == actual_skin_name
+    # Set default skin in initial one (if initial skin still exist) 
+    # or in 1st from available skin names list.
+    current_default_skin = skinsTool.getDefaultSkin()
+    if current_default_skin == actual_skin_name:
+        if initial_skin in skin_names :
+            skinsTool.manage_properties(default_skin=initial_skin, REQUEST=None)
+        elif len(skin_names)>0 :
+            skinsTool.manage_properties(default_skin=skin_names[0], REQUEST=None)
+
+def addProperty(p_sheet, p_id, p_value, p_type, out):
+    if p_sheet.hasProperty(p_id):
+        p_sheet._delProperty(p_id)
+    p_sheet._setProperty(p_id, p_value, p_type)
+    print >> out, "... added %%s PropertySheet to %%s." %% (p_id, p_sheet.getId())
+
+def getResourceProperties(obj, prop_list, dflt=''):
+    """ Return list of 2 items list-[property name, property value]."""
+    properties=[]
+    for prop in prop_list:
+        accessor = getattr(obj, 'get%%s' %% prop.capitalize(), None)
+        if accessor:
+            properties.append([prop, accessor() or dflt])
+    return properties
+
+def registerResource(pp_up, portal_res, resRegisterFunction, out \
+                    ,RESOURCE_SKIN_LIST, SKIN_RES_REGDATA, UP_PROPERTY, RES_REG_PROPS):
+    """ Register resources in portal's registry, remember existant settings."""
+    # Get original registered resources
+    portal_res_srings = []
+    for r in portal_res.getResources():
+        portal_res_srings.append(";".join(['%%s::%%s'%%(r[0],str(r[1])) \
+                                for r in getResourceProperties(r, RES_REG_PROPS)]))
+    addProperty(pp_up, UP_PROPERTY, portal_res_srings, 'lines', out)
+    # Tune Resource registry according to new skin needs
+    unexistent = [] # list of default resources, 
+                    # which present in Skin-product, BUT absent in portal
+    portal_res_ids = portal_res.getResourceIds()
+    for res_dict in SKIN_RES_REGDATA:
+        if res_dict['id'] not in portal_res_ids:
+            # It's interesting - Resource Registry allow adding unexistent resource - use this
+            resRegisterFunction(**res_dict)
+            if res_dict['id'] not in RESOURCE_SKIN_LIST:
+                unexistent.append(res_dict['id'])
+        else:
+            pos = portal_res.getResourcePosition(res_dict['id'])
+            portal_res.unregisterResource(res_dict['id'])
+            resRegisterFunction(**res_dict)
+            portal_res.moveResource(res_dict['id'], pos)
+    if unexistent:
+        print >> out, "!!! - BAD: your Resource Regestry have'nt %%s resource(s), which may lead to some problems." %% unexistent
+
+def getVersion(res_list):
+    """Check version of skin product generator."""
+    return (res_list and not '::' in res_list[0] and '0.5') or '0.7'
+
+def uninstallResource(portal_res, original_res_list, RESOURCE_SKIN_LIST, resRegisterFunction):
+    # Prepare Resource Registry data for backup to original state
+    original_res_regestry = {}
+    genVersion = getVersion(original_res_list)
+    for rec in original_res_list:
+        resource = {}
+        if genVersion == '0.7':
+            [resource.update({prop.split('::')[0]:prop.split('::')[1]}) for prop in rec.split(";")]
+        elif genVersion == '0.5':
+            props = rec.split(";")
+            [resource.update({CSS_BASE_IDS_QPSD053[i]:props[i]}) for i in range(len(CSS_BASE_IDS_QPSD053))]
+        original_res_regestry[resource.pop('id')] = resource
+    # Work up actual Resource Registry
+    res_dict = portal_res.getResourcesDict()
+    for res_id in res_dict.keys():
+        # Remove from Resource Registry Skin product's resources
+        if res_id in RESOURCE_SKIN_LIST \
+           and res_id not in original_res_regestry.keys():
+            portal_res.unregisterResource(res_id)
+            continue
+        # Backup 'enabled' property Registry's resourses to it's original state
+        if original_res_regestry.has_key(res_id):
+            act_Enabled_state = res_dict[res_id].getEnabled()
+            orig_Enabled_state = original_res_regestry[res_id]['enabled']
+            if act_Enabled_state != orig_Enabled_state:
+                pos = portal_res.getResourcePosition(res_id)
+                resource = res_dict[res_id]
+                res = original_res_regestry[res_id]
+                portal_res.unregisterResource(res_id)
+                resRegisterFunction(res_id, **res)
+                portal_res.moveResource(res_id, pos)
+
+def customizeSlots(portal, pp_up, out):
+    # Get original Site's column lists
+    orig_left_slots = left_column = list(portal.left_slots)
+    orig_right_slots = right_column = list(portal.right_slots)
+    # Save original Site's LEFT and RIGHT slots
+    addProperty(pp_up, 'q_left_slots', orig_left_slots, 'lines', out)
+    addProperty(pp_up, 'q_right_slots', orig_right_slots, 'lines', out)
+    # blend-with-site - to portal's slots adding only new one from skin-porduct
+    # blend-with-skin - portal slots forming in the following manner: 
+    #                   first adding skin-porduct's slots, than new one from portal
+    # replace - to portal's slots forming only from the skin-porduct's slot list
+    if SLOT_FORMING == "blend_with_skin":
+        left_column, right_column = formSlotsColumn(LEFT_SLOTS, RIGHT_SLOTS, 
+                                                    orig_left_slots, orig_right_slots, MAIN_COLUMN)
+    elif SLOT_FORMING == "blend_with_site":
+        left_column, right_column = formSlotsColumn(orig_left_slots, orig_right_slots,
+                                                    LEFT_SLOTS, RIGHT_SLOTS, MAIN_COLUMN )
+    elif SLOT_FORMING == "replace":
+        left_column, right_column = formSlotsColumn(LEFT_SLOTS, RIGHT_SLOTS, [], [], MAIN_COLUMN)
+    # REPLACE SITE's column slots
+    portal.left_slots = tuple(left_column)
+    portal.right_slots = tuple(right_column)
+    print >> out, "Complited portal slots customization ..."
+
+# main_column ("left" / "right" / "both") mean which of the MAIN column is favour
+def formSlotsColumn(main_left, main_right, slave_left=[], slave_right=[], main_column="both"):
+    result_left = main_left
+    result_right = main_right
+    if main_column == "left":
+    # 1) APPEND to MAIN_LEFT list *new for main_left column* slots from slave_left list 
+    # 2) APPEND to MAIN_RIGHT list *new for both main columns* slots from slave_right
+    # 3) REMOVE slots from MAIN_RIGHT list, which are *doubled* in MAIN_LEFT
+        [result_left.append(slot) for slot in slave_left if slot not in result_left]
+        [result_right.append(slot) for slot in slave_right \
+                                   if slot not in result_right and slot not in result_left]
+        [result_right.remove(slot) for slot in result_left if slot in result_right]
+    elif main_column == "right":
+    # 1) APPEND to MAIN_LEFT list *new for main_right column* slots from slave_left list 
+    # 2) APPEND to MAIN_RIGHT list *new for both main columns* slots from slave_right
+    # 3) REMOVE slots from MAIN_LEFT list, which are *doubled* in MAIN_RIGHT
+        [result_right.append(slot) for slot in slave_right if slot not in result_right]
+        [result_left.append(slot) for slot in slave_left \
+                                  if slot not in result_left and slot not in result_right]
+        [result_left.remove(slot) for slot in result_right if slot in result_left]
+    elif main_column == "both":
+    # 1) APPEND to MAIN_LEFT list *new for both main columns* slots from slave_left list 
+    # 2) APPEND to MAIN_RIGHT list *new for both main columns* slots from slave_right
+        [result_left.append(slot) for slot in slave_left \
+                                  if slot not in result_left and slot not in result_right]
+        [result_right.append(slot) for slot in slave_right \
+                                   if slot not in result_right and slot not in result_left]
+    return [result_left, result_right]
+
+def getProperty(pp, ps, id, default=[]):
+    """ Get property from portal_properties/[property_sheet]"""
+    res = default
+    if ps in pp.objectIds() and pp[ps].hasProperty(id):
+        res = pp[ps].getProperty(id, default)
+    return res
+
+
+###################################
+## OLD INSTALL
+
+def prepareInstallation(portal, pp, out):
+    #uninstallOtherSkinProducts(portal)
+    if not ('uninstall_properties' in pp.objectIds()) :
+        pp.addPropertySheet(id='uninstall_properties', title= 'uninstall_properties')
+        print >> out, "Created 'portal_properties.uninstall_properties' PropertySheet (UP) for backup purpose"
+    return pp.uninstall_properties
+CHECKED_MESSAGE = "The base installation checkings completed."
+
+def uninstallOtherSkinProducts(portal):
+    qi=getToolByName(portal, 'portal_quickinstaller', None)
+    if not qi:
+        raise Exception("Can't work without QuickInstaller tool.")
+    # Get installed products
+    installed_products = [getattr(qi, p_dict['id']) \
+                          for p_dict in qi.listInstalledProducts()
+                          if p_dict['id'] != PRODUCT_NAME]
+    seek_str = "%%s generated product" %% GENERATOR_PRODUCT
+    installed_skin_products = []
+    # Looking for installed skin-products
+    for p in installed_products:
+        transcript = p.getTranscriptAsText()
+        if transcript.find(seek_str) >= 0 :
+            installed_skin_products.append(p.getId())
+    # Uninstall found skin-products
+    if installed_skin_products:
+        qi.uninstallProducts(products=installed_skin_products)
+
+###################################
+## Prepare UNINSTALL
+
+def prepareUninstallSkin(portal, pp_up, out): # ??
+    # Checking for presense SKIN_NAME in portal_skins directory view or among Skin Names
+    skinsTool = getToolByName(portal, 'portal_skins')
+    # Get unique product_skin_name and remember it in case of differ from SKIN_NAME.
+    default_skin = skinsTool.getDefaultSkin()
+    addProperty(pp_up, 'q_default_skin', default_skin, 'string', out)
Index: qPloneSkinDump/trunk/skin_template/utilsPortlets.py
===================================================================
--- qPloneSkinDump/trunk/skin_template/utilsPortlets.py	(revision 74)
+++ qPloneSkinDump/trunk/skin_template/utilsPortlets.py	(revision 74)
@@ -0,0 +1,153 @@
+from zope.interface import providedBy
+from zope.schema import getFields
+from zope.component import getMultiAdapter, getUtility, getSiteManager
+
+from plone.portlets.interfaces import IPortletAssignmentMapping, IPortletManager, IPlacelessPortletManager
+from plone.portlets.interfaces import IPortletContext, IPortletDataProvider
+from plone.portlets.interfaces import ILocalPortletAssignmentManager
+
+from Products.CMFCore.utils import getToolByName
+from Products.GenericSetup.utils import _getDottedName, _resolveDottedName
+
+
+def extractInfoFromAssignment(name, assignment):
+    klass = assignment.__class__
+    a = {'name' : name, 'class' : '%s' % _getDottedName(klass)}
+    data = assignment.data
+    kwargs = {}
+    for i in list(providedBy(data)):
+        if i.isOrExtends(IPortletDataProvider):
+            for field_name, field in getFields(i).items():
+                kwargs[field_name] = field.get(assignment)
+    a['kwargs'] = kwargs
+    return a
+
+def extractSiteWidePortlets(context, managers):
+    """ Extract site-wide portlets 
+        Data structure:
+            '__site-wide-portlets__', [(<manager1_name>, <manager1_info>),
+                                       (<manager2_name>, <manager2_info>),
+                                       (<manager3_name>, <manager3_info>)])
+            <manager_info>:
+                {'category1' : <catmapping1>,
+                 'category2' : <catmapping2>}
+            <catmapping>:
+                {'key1' : <mapping1>,
+                 'key2' : <mapping2>}
+            <mapping>:
+                {'assignment_name1' : <assignment1>,
+                 'assignment_name2' : <assignment2>}
+            <assignment>:
+                {'name'   : 'Assignment',
+                 'class'  : 'dotted.path.to.assignment.class',
+                 'kwargs' : {'parameter1' : 'value1',
+                             'parameter2' : 'value2'}
+    """
+    info = []
+    for manager_name, manager in managers:
+        manager_info = {}
+        for category, catmapping in manager.items():
+            catmapping_info = {}
+            for key, mapping in catmapping.items():
+                mapping_info = {}
+                for name, assignment in mapping.items():
+                    mapping_info[name] = extractInfoFromAssignment(name, assignment)
+                catmapping_info[key] = mapping_info
+            manager_info[category] = catmapping_info
+        info.append((manager_name, manager_info))
+    return info
+
+def extractContextPortletsFromManager(context, manager):
+    """ Extract all contextual portlets from given object and portlet manager, and portlets blacklists
+        Data structure:
+        <manager_info> =
+            {'blacklists'  : [(GROUP_CATEGORY, True),
+                              (CONTENT_TYPE_CATEGORY, False),
+                              (CONTEXT_CATEGORY, None)],
+             'assignments' : [{'name'   : 'Assignment-2',
+                               'class'  : 'dotted.path.to.assignment.class',
+                               'kwargs' : {'parameter1' : 'value1',
+                                          'parameter2' : 'value2'}},
+                              {'name'   : 'Assignment',
+                               'class'  : 'dotted.path.to.assignment.class',
+                               'kwargs' : {'parameter1' : 'value1',
+                                            'parameter2' : 'value2'}]}
+    """
+
+    info = {}
+    info['assignments'] = assignments = []
+    info['blacklists'] = blacklists = []
+
+    # Extract contextual portlets
+    mapping = getMultiAdapter((context, manager), IPortletAssignmentMapping, context=context)
+    for name, assignment in mapping.items():
+        assignments.append(extractInfoFromAssignment(name, assignment))
+
+    # Extract blacklists for given object and manager
+    localassignmentmanager = getMultiAdapter((context, manager), ILocalPortletAssignmentManager)
+    blacklist = localassignmentmanager._getBlacklist()
+    if blacklist is not None:
+        for category, key in blacklist.items():
+            blacklists.append((category, key))
+
+    return info
+
+def extractPortletsFromContext(context, slot_structure, typesToShow, managers):
+    """ Extract portlets for given object assigned through all portlet managers.
+        Data structure:
+            ('unique/path/to/context', [(<manager1_name>, <manager1_info>),
+                                        (<manager2_name>, <manager2_info>),
+                                        (<manager3_name>, <manager3_info>)])
+    """
+
+
+    info = []
+    key = '/'.join(context.getPhysicalPath()[2:])
+
+    for name, manager in managers:
+        info.append((name, extractContextPortletsFromManager(context, manager)))
+
+    slot_structure.append((key, info))
+
+    return slot_structure
+
+def dumpAllPortlets(context, slot_structure, typesToShow, managers):
+    extractPortletsFromContext(context, slot_structure, typesToShow, managers)
+    if getattr(context.aq_base, 'isPrincipiaFolderish', 0):
+        for id, obj in context.contentItems():
+            if obj.portal_type in typesToShow:
+                dumpAllPortlets(obj, slot_structure, typesToShow, managers)
+
+    return slot_structure
+
+def dumpPortlets(context, dump_policy, dump_portlets_selection):
+    """ Extract portlets from given set of objects and site-wide portlets too.
+        Data structure:
+            SLOT_STRUCTURE =
+                [(), (), ()]
+    """
+
+    portal = getToolByName(context, 'portal_url').getPortalObject()
+    portal_state = getMultiAdapter((portal, context.REQUEST), name=u'plone_portal_state')
+    typesToShow = portal_state.friendly_types()
+
+    components = getSiteManager(context)
+    managers = [r for r in components.registeredUtilities() if r.provided.isOrExtends(IPortletManager)]
+    context_managers = [(m.name, getUtility(IPortletManager, name=m.name, context=context)) for m in managers
+                                                                               if not IPlacelessPortletManager.providedBy(m.component)]
+    managers = [(m.name, getUtility(IPortletManager, name=m.name, context=context)) for m in managers]
+
+    slot_structure = []
+    if dump_policy == 'root':
+        extractPortletsFromContext(portal, slot_structure, typesToShow, context_managers)
+    elif dump_policy == 'all':
+        dumpAllPortlets(portal, slot_structure, typesToShow, context_managers)
+    elif dump_policy == 'selection':
+        for ppath in dump_portlets_selection:
+            obj = portal.restrictedTraverse(ppath)
+            extractPortletsFromContext(obj, slot_structure, typesToShow, context_managers)
+
+    slot_structure.append(('__site-wide-portlets__', extractSiteWidePortlets(portal, managers)))
+
+    return slot_structure
+
