Index: qLocalSkin/tags/0.2/__init__.py
===================================================================
--- qLocalSkin/tags/0.2/__init__.py	(revision 505)
+++ qLocalSkin/tags/0.2/__init__.py	(revision 505)
@@ -0,0 +1,40 @@
+from Products.CMFPlone.URLTool import URLTool
+
+from adapters.interfaces import IRequestPortalUrlAnnotator
+
+## XXX PATCH FOR FILERESOURCE, UNTILL ADD 'POST' METHOD OR FIX 
+## ResourceRegistries.tools.BaseRegistry.BaseRegistryTool.getResourceContent method
+marker = []
+from Products.Five.browser.resource import FileResource
+
+if getattr(FileResource, 'POST', marker) == marker:
+    FileResource.POST = FileResource.GET
+
+def urltool_call(self, relative=0, *args, **kw):
+    """ Get by default the absolute URL of the portal. If request is annonated then add suffix to portal_url
+    """
+    # print '################################ Called patched portal_url __call__: ' + self.REQUEST.URL
+    url_suffix = ''
+    if self.REQUEST:
+        annotator = IRequestPortalUrlAnnotator(self.REQUEST, None)
+        if annotator is not None:
+            url_suffix = annotator.getPortalUrlSuffix(default=marker)
+            if not url_suffix == marker:
+                return url_suffix
+    return self.getPortalObject().absolute_url(relative=relative)
+
+def urltool_getPortalPath(self):
+    """ Get the portal object's URL without the server URL component.
+    """
+
+    url_suffix = ''
+    if self.REQUEST:
+        annotator = IRequestPortalUrlAnnotator(self.REQUEST, None)
+        if annotator is not None:
+            url_suffix = annotator.getPortalUrlSuffix()
+            # print '############ Added sufix to portal_url: ' + url_suffix
+
+    return '/'.join(self.getPortalObject().getPhysicalPath()) + url_suffix
+
+URLTool.__call__ = urltool_call
+#URLTool.getPortalPath = urltool_getPortalPath
Index: qLocalSkin/tags/0.2/adapters/__init__.py
===================================================================
--- qLocalSkin/tags/0.2/adapters/__init__.py	(revision 505)
+++ qLocalSkin/tags/0.2/adapters/__init__.py	(revision 505)
@@ -0,0 +1,1 @@
+#
Index: qLocalSkin/tags/0.2/adapters/configure.zcml
===================================================================
--- qLocalSkin/tags/0.2/adapters/configure.zcml	(revision 505)
+++ qLocalSkin/tags/0.2/adapters/configure.zcml	(revision 505)
@@ -0,0 +1,17 @@
+<configure xmlns="http://namespaces.zope.org/zope"
+           xmlns:browser="http://namespaces.zope.org/browser"
+           xmlns:five="http://namespaces.zope.org/five">
+
+    <adapter
+        factory=".skinnameextractor.SkinNameExtractor"
+        provides=".interfaces.ISkinNameExtractor"
+        for="Products.qLocalSkin.interfaces.IShiftPortalUrl"
+        />
+
+    <adapter
+        factory=".requestannotator.RequestPortalUrlAnnotator"
+        provides=".interfaces.IRequestPortalUrlAnnotator"
+        for="zope.publisher.interfaces.browser.IBrowserRequest"
+        />
+
+</configure>
Index: qLocalSkin/tags/0.2/adapters/interfaces.py
===================================================================
--- qLocalSkin/tags/0.2/adapters/interfaces.py	(revision 505)
+++ qLocalSkin/tags/0.2/adapters/interfaces.py	(revision 505)
@@ -0,0 +1,21 @@
+from zope.interface import Interface, Attribute
+
+class ISkinNameExtractor(Interface):
+
+    property_name = Attribute('property_name', 'property name for extraction from context')
+
+    def getSkinName():
+        """ Returns a skin name from context object. """
+
+    def setSkinName(value):
+        """ Set a value in skin name property if last exists """
+
+class IRequestPortalUrlAnnotator(Interface):
+
+    key = Attribute('key', 'Key for saving in request annotations')
+
+    def annotate(value):
+        """ Set portal_url sufix in request's annotation to value. """
+
+    def getPortalUrlSuffix():
+        """ Extract portal_url suffix from request's annotation by 'key' key. """
Index: qLocalSkin/tags/0.2/adapters/requestannotator.py
===================================================================
--- qLocalSkin/tags/0.2/adapters/requestannotator.py	(revision 505)
+++ qLocalSkin/tags/0.2/adapters/requestannotator.py	(revision 505)
@@ -0,0 +1,31 @@
+from zope.interface import implements
+from zope.component import adapts
+from zope.publisher.interfaces.browser import IBrowserRequest
+from zope.annotation.interfaces import IAnnotations
+
+from Products.qLocalSkin.config import ANNOTATION_KEY
+from interfaces import IRequestPortalUrlAnnotator
+
+class RequestPortalUrlAnnotator(object):
+    """ Adapter for working with portal_url suffix in request's annotation. """
+
+    implements(IRequestPortalUrlAnnotator)
+    adapts(IBrowserRequest)
+
+    key = ANNOTATION_KEY
+
+    def __init__(self, request):
+        self.request = request
+        self.annotations = IAnnotations(self.request, None)
+
+    def annotate(self, value):
+        if self.annotations is not None:
+            self.annotations[self.key] = value
+            # print "################## Setted annotation on request from qLocalSkin: " + str(value)
+            return True
+        return False
+
+    def getPortalUrlSuffix(self, default=''):
+        if self.annotations is not None:
+            return self.annotations.get(self.key, default)
+        return default
Index: qLocalSkin/tags/0.2/adapters/skinnameextractor.py
===================================================================
--- qLocalSkin/tags/0.2/adapters/skinnameextractor.py	(revision 505)
+++ qLocalSkin/tags/0.2/adapters/skinnameextractor.py	(revision 505)
@@ -0,0 +1,27 @@
+from zope.component import adapts
+from zope.interface import implements
+
+from Products.qLocalSkin.interfaces import IShiftPortalUrl
+from interfaces import ISkinNameExtractor
+from Products.qLocalSkin.config import PROPERTY_NAME
+
+class SkinNameExtractor(object):
+    """ Extract skin name from context's properties. """
+
+    implements(ISkinNameExtractor)
+    adapts(IShiftPortalUrl)
+
+    property_name = PROPERTY_NAME
+
+    def __init__(self, context):
+        self.context = context
+
+    def getSkinName(self):
+        skin_name = self.context.getProperty(self.property_name, d=None)
+        return skin_name
+
+    def setSkinName(self, value):
+        if self.context.hasProperty(self.property_name):
+            self.context.manage_changeProperies(**{self.property_name:value})
+            return True
+        return False
Index: qLocalSkin/tags/0.2/browser/__init__.py
===================================================================
--- qLocalSkin/tags/0.2/browser/__init__.py	(revision 505)
+++ qLocalSkin/tags/0.2/browser/__init__.py	(revision 505)
@@ -0,0 +1,1 @@
+#
Index: qLocalSkin/tags/0.2/browser/configure.zcml
===================================================================
--- qLocalSkin/tags/0.2/browser/configure.zcml	(revision 505)
+++ qLocalSkin/tags/0.2/browser/configure.zcml	(revision 505)
@@ -0,0 +1,25 @@
+<configure xmlns="http://namespaces.zope.org/zope"
+           xmlns:five="http://namespaces.zope.org/five">
+
+    <!-- provide security for adapter classes -->
+    <class class=".localPortalState.LocalPortalState">
+        <require permission="zope2.View"
+                 interface="plone.app.layout.globals.interfaces.IPortalState" />
+    </class>
+
+    <class class=".styles.StylesView">
+        <require permission="zope.Public"
+                 interface="Products.ResourceRegistries.browser.interfaces.IStylesView" />
+    </class>
+
+    <class class=".scripts.ScriptsView">
+        <require permission="zope.Public"
+                 interface="Products.ResourceRegistries.browser.interfaces.IScriptsView" />
+    </class>
+
+    <class class=".kss.KSSView">
+        <require permission="zope.Public"
+                 interface="Products.ResourceRegistries.browser.interfaces.IKSSView" />
+    </class>
+
+</configure>
Index: qLocalSkin/tags/0.2/browser/interfaces.py
===================================================================
--- qLocalSkin/tags/0.2/browser/interfaces.py	(revision 505)
+++ qLocalSkin/tags/0.2/browser/interfaces.py	(revision 505)
@@ -0,0 +1,5 @@
+from zope.publisher.interfaces.browser import IDefaultBrowserLayer
+
+class IThemeCustomViews(IDefaultBrowserLayer):
+    """Marker interface that defines a Zope 3 skin layer.
+        """
Index: qLocalSkin/tags/0.2/browser/kss.py
===================================================================
--- qLocalSkin/tags/0.2/browser/kss.py	(revision 505)
+++ qLocalSkin/tags/0.2/browser/kss.py	(revision 505)
@@ -0,0 +1,17 @@
+from Products.CMFCore.utils import getToolByName
+from Products.ResourceRegistries.browser.kss import KSSView as base
+
+class KSSView(base):
+    """ Information for kss rendering. """
+
+    def kineticstylesheets(self):
+        ksses = super(KSSView, self).kineticstylesheets()
+        portal_url = getToolByName(self.context, 'portal_url')
+        new_url = portal_url()
+        portal_url = portal_url.getPortalObject().absolute_url()
+        for kss in ksses:
+            src = kss.get('src', '')
+            if src != '':
+                kss['src'] = src.replace(portal_url, new_url, 1)
+        return ksses
+
Index: qLocalSkin/tags/0.2/browser/localPortalState.py
===================================================================
--- qLocalSkin/tags/0.2/browser/localPortalState.py	(revision 505)
+++ qLocalSkin/tags/0.2/browser/localPortalState.py	(revision 505)
@@ -0,0 +1,18 @@
+from zope.interface import implements
+from plone.memoize.view import memoize_contextless
+from plone.app.layout.globals.portal import PortalState
+from plone.app.layout.globals.interfaces import IPortalState
+
+from Products.qLocalSkin.interfaces import IShiftPortalUrl
+
+class LocalPortalState(PortalState):
+    implements(IPortalState)
+
+    @memoize_contextless
+    def portal_url(self):
+        """ Return url to container, which provided
+	    IShiftPortalUrl marker interface, as portal_url.
+	    Use functionality of portal_url's __call__ method
+	    patch.
+        """
+        return self.context.portal_url()
Index: qLocalSkin/tags/0.2/browser/scripts.py
===================================================================
--- qLocalSkin/tags/0.2/browser/scripts.py	(revision 505)
+++ qLocalSkin/tags/0.2/browser/scripts.py	(revision 505)
@@ -0,0 +1,16 @@
+from Products.CMFCore.utils import getToolByName
+from Products.ResourceRegistries.browser.scripts import ScriptsView as base
+
+class ScriptsView(base):
+    """ Information for script rendering. """
+
+    def scripts(self):
+        scripts = super(ScriptsView, self).scripts()
+        portal_url = getToolByName(self.context, 'portal_url')
+        new_url = portal_url()
+        portal_url = portal_url.getPortalObject().absolute_url()
+        for script in scripts:
+            src = script.get('src', '')
+            if src != '':
+                script['src'] = src.replace(portal_url, new_url, 1)
+        return scripts
Index: qLocalSkin/tags/0.2/browser/styles.py
===================================================================
--- qLocalSkin/tags/0.2/browser/styles.py	(revision 505)
+++ qLocalSkin/tags/0.2/browser/styles.py	(revision 505)
@@ -0,0 +1,16 @@
+from Products.CMFCore.utils import getToolByName
+from Products.ResourceRegistries.browser.styles import StylesView as base
+
+class StylesView(base):
+    """ Information for style rendering. """
+
+    def styles(self):
+        styles = super(StylesView, self).styles()
+        portal_url = getToolByName(self.context, 'portal_url')
+        new_url = portal_url()
+        portal_url = portal_url.getPortalObject().absolute_url()
+        for style in styles:
+            src = style.get('src', '')
+            if src != '':
+                style['src'] = src.replace(portal_url, new_url, 1)
+        return styles
Index: qLocalSkin/tags/0.2/componentregistry.xml
===================================================================
--- qLocalSkin/tags/0.2/componentregistry.xml	(revision 505)
+++ qLocalSkin/tags/0.2/componentregistry.xml	(revision 505)
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<componentregistry>
+ <adapters>
+  <adapter name="plone_portal_state"
+     factory="Products.qLocalSkin.browser.localPortalState.LocalPortalState"
+     for_="zope.interface.Interface
+           zope.publisher.interfaces.browser.IBrowserRequest"
+     provides="plone.app.layout.globals.interfaces.IPortalState"/>
+  <adapter name="resourceregistries_kss_view"
+     factory="Products.qLocalSkin.browser.kss.KSSView"
+     for_="zope.interface.Interface
+           zope.publisher.interfaces.browser.IBrowserRequest"
+     provides="zope.publisher.interfaces.browser.IBrowserView"/>
+  <adapter name="resourceregistries_scripts_view"
+     factory="Products.qLocalSkin.browser.scripts.ScriptsView"
+     for_="zope.interface.Interface
+           zope.publisher.interfaces.browser.IBrowserRequest"
+     provides="zope.publisher.interfaces.browser.IBrowserView"/>
+  <adapter name="resourceregistries_styles_view"
+     factory="Products.qLocalSkin.browser.styles.StylesView"
+     for_="zope.interface.Interface
+           zope.publisher.interfaces.browser.IBrowserRequest"
+     provides="zope.publisher.interfaces.browser.IBrowserView"/>
+ </adapters>
+ <utilities/>
+</componentregistry>
Index: qLocalSkin/tags/0.2/config.py
===================================================================
--- qLocalSkin/tags/0.2/config.py	(revision 505)
+++ qLocalSkin/tags/0.2/config.py	(revision 505)
@@ -0,0 +1,3 @@
+
+ANNOTATION_KEY = 'qLocalSkin.portal_url.suffix'
+PROPERTY_NAME = 'skin_name'
Index: qLocalSkin/tags/0.2/configure.zcml
===================================================================
--- qLocalSkin/tags/0.2/configure.zcml	(revision 505)
+++ qLocalSkin/tags/0.2/configure.zcml	(revision 505)
@@ -0,0 +1,13 @@
+<configure xmlns="http://namespaces.zope.org/zope"
+           xmlns:five="http://namespaces.zope.org/five">
+
+    <include package=".browser"/>
+
+    <include package=".adapters"/>
+
+    <include file="events.zcml"/>
+
+    <!-- marker interface for shift Portal URL to marked folder -->
+    <interface interface=".interfaces.IShiftPortalUrl" />
+
+</configure>
Index: qLocalSkin/tags/0.2/events.zcml
===================================================================
--- qLocalSkin/tags/0.2/events.zcml	(revision 505)
+++ qLocalSkin/tags/0.2/events.zcml	(revision 505)
@@ -0,0 +1,10 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope">
+
+    <subscriber
+        for="Products.qLocalSkin.interfaces.IShiftPortalUrl
+             zope.app.publication.interfaces.IBeforeTraverseEvent"
+        handler=".layer.mark_layer"
+        />
+
+</configure>
Index: qLocalSkin/tags/0.2/interfaces.py
===================================================================
--- qLocalSkin/tags/0.2/interfaces.py	(revision 505)
+++ qLocalSkin/tags/0.2/interfaces.py	(revision 505)
@@ -0,0 +1,6 @@
+from zope.interface import Interface
+
+class IShiftPortalUrl(Interface):
+    """ Marker interface for shift portal_url
+        to location of marked folder.
+    """
Index: qLocalSkin/tags/0.2/layer.py
===================================================================
--- qLocalSkin/tags/0.2/layer.py	(revision 505)
+++ qLocalSkin/tags/0.2/layer.py	(revision 505)
@@ -0,0 +1,23 @@
+from zope.component import queryUtility, queryMultiAdapter
+
+from zope.publisher.interfaces.browser import IBrowserSkinType
+from zope.publisher.browser import applySkin
+
+from adapters.interfaces import ISkinNameExtractor, IRequestPortalUrlAnnotator
+
+def mark_layer(context, event):
+    """Mark the request with a layer corresponding to the current marked object.
+    """
+
+    skin_name = None
+    extractor = ISkinNameExtractor(context, None)
+    if extractor is not None:
+        skin_name = extractor.getSkinName()
+    if skin_name is not None:
+        skin = queryUtility(IBrowserSkinType, name=skin_name)
+        if skin is not None:
+            applySkin(event.request, skin)
+            context.changeSkin(skin_name, event.request)
+            annotator = IRequestPortalUrlAnnotator(event.request, None)
+            if annotator is not None:
+                annotator.annotate(context.absolute_url())
Index: qLocalSkin/tags/0.2/version.txt
===================================================================
--- qLocalSkin/tags/0.2/version.txt	(revision 505)
+++ qLocalSkin/tags/0.2/version.txt	(revision 505)
@@ -0,0 +1,1 @@
+0.2.0
