Commit 3347e3f9 authored by Rafael Monnerat's avatar Rafael Monnerat

Update from upstream/master

parents 2718c9f4 b1dcfe05
Pipeline #35580 failed with stage
in 0 seconds
......@@ -16,18 +16,6 @@ request_form = context.ERP5Site_filterParameterList(request_form)
request_form.update(keep_items)
# XXX Allow CORS
response = context.REQUEST.RESPONSE
context.Base_prepareCorsResponse(RESPONSE=response)
# http://en.wikipedia.org/wiki/Post/Redirect/Get
response.setStatus(201, lock=True)
response.setHeader("X-Location", "urn:jio:get:%s" % context.getRelativeUrl())
# be explicit with the reponse content type because in case of reports - they
# can be in text/plain, application/pdf ... so the RJS form needs to know what
# is going exactly on. ERP5Document_getHateoas returns application/hal+json
# therefor we don't need to be afraid of clashes
response.setHeader("Content-type", "application/json; charset=utf-8")
portal_status_level = keep_items.pop("portal_status_level", "success")
if portal_status_level in ("warning", "error", "fatal"):
portal_status_level = "error"
......@@ -70,8 +58,20 @@ if (form_id not in [None, 'Base_viewFakePythonScriptActionForm', 'Base_viewFakeJ
)
}
# XXX Allow CORS
response = context.REQUEST.RESPONSE
context.Base_prepareCorsResponse(RESPONSE=response)
response.setHeader("X-Location", "urn:jio:get:%s" % context.getRelativeUrl())
# be explicit with the reponse content type because in case of reports - they
# can be in text/plain, application/pdf ... so the RJS form needs to know what
# is going exactly on. ERP5Document_getHateoas returns application/hal+json
# therefor we don't need to be afraid of clashes
response.setHeader("Content-type", "application/json; charset=utf-8")
result = json.dumps(result_dict, indent=2)
# http://en.wikipedia.org/wiki/Post/Redirect/Get
response.setStatus(201, lock=True)
if abort_transaction:
response.setBody(result, lock=True)
raise Redirect('')
......
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Base Type" module="erp5.portal_type"/>
<global name="Delivery Type" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......@@ -68,6 +68,10 @@
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>type_class</string> </key>
<value> <string>AccountingTransaction</string> </value>
</item>
</dictionary>
</pickle>
</record>
......
......@@ -21,8 +21,8 @@ elif code is not None:
code,
"{0}/ERP5Site_callbackFacebookLogin".format(context.absolute_url()))
if response_dict is not None:
access_token = response_dict['access_token'].encode('utf-8')
hash_str = context.Base_getHMAC(access_token, access_token)
access_token = response_dict['access_token']
hash_str = context.Base_getHMAC(access_token.encode('utf-8'), access_token.encode('utf-8'))
context.setAuthCookie(response, '__ac_facebook_hash', hash_str)
# store timestamp in second since the epoch in UTC is enough
......
##############################################################################
# Copyright (c) 2024 Nexedi SA and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
from AccessControl import ClassSecurityInfo
import random
import string
import time
import oauthlib.oauth2
import requests
from zExceptions import Unauthorized
from Products.ERP5Type.XMLObject import XMLObject
from Products.ERP5Type import Permissions
from Products.ERP5Type.Utils import unicode2str
from Products.ERP5Type.Timeout import getTimeLeft
AUTH_URL = 'https://accounts.google.com/o/oauth2/auth'
TOKEN_URL = 'https://accounts.google.com/o/oauth2/token'
USER_INFO_URL = 'https://www.googleapis.com/oauth2/v1/userinfo'
SCOPE_LIST = ['https://www.googleapis.com/auth/userinfo.profile',
'https://www.googleapis.com/auth/userinfo.email']
# Default timeout (in seconds) for the HTTP request made to google servers to
# exchange the authorization code for a token.
DEFAULT_HTTP_TIMEOUT = 10
class GoogleConnector(XMLObject):
meta_type = 'ERP5 Google Connector'
portal_type = 'Google Connector'
security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
@security.public
def redirectToGoogleLoginPage(self, redirect_uri, RESPONSE):
"""Redirect to authorization page.
"""
authorization_url = self._getOAuthlibClient().prepare_request_uri(
uri=AUTH_URL,
redirect_uri=redirect_uri,
scope=SCOPE_LIST,
access_type="offline",
include_granted_scopes='true',
prompt="consent",
state=self._getAuthorizationState(),
)
return RESPONSE.redirect(authorization_url)
@security.public # XXX public but not publishable
def getTokenFromCode(self, state, code, redirect_uri):
self._verifyAuthorizationState(state)
body = self._getOAuthlibClient().prepare_request_body(
code=code,
client_secret=self.getSecretKey(),
redirect_uri=redirect_uri,
)
resp = requests.post(
TOKEN_URL,
data=body,
headers={'Content-Type': 'application/x-www-form-urlencoded'},
timeout=self._getTimeout(),
)
__traceback_info__ = (resp.content, resp.status_code)
resp.raise_for_status()
return self._getGoogleTokenFromJSONResponse(resp.json())
@security.private
def refreshToken(self, token):
"""Refresh auth token.
Used by Products.ERP5Security.ERP5ExternalOauth2ExtractionPlugin
"""
body = self._getOAuthlibClient().prepare_refresh_body(
client_id=self.getClientId(),
client_secret=self.getSecretKey(),
access_type="offline",
refresh_token=token['refresh_token'],
)
resp = requests.post(
TOKEN_URL,
data=body,
headers={'Content-Type': 'application/x-www-form-urlencoded'},
timeout=self._getTimeout(),
)
if not resp.ok:
return {}
return self._getGoogleTokenFromJSONResponse(resp.json())
@security.private
def getUserEntry(self, access_token):
resp = requests.get(
USER_INFO_URL,
headers={'Authorization': 'Bearer {}'.format(access_token)},
timeout=self._getTimeout(),
)
resp.raise_for_status()
google_entry = resp.json()
user_entry = {}
# remap user info
for erp5_key, google_key in (
('first_name', 'given_name'),
('last_name', 'family_name'),
('email', 'email'),
('reference', 'email'),
):
user_entry[erp5_key] = unicode2str(google_entry.get(google_key, ''))
return user_entry
def _getOAuthlibClient(self):
return oauthlib.oauth2.WebApplicationClient(
self.getClientId(),
access_type="offline",
)
def _getGoogleTokenFromJSONResponse(self, token):
return {
'access_token': unicode2str(token['access_token']),
'refresh_token': unicode2str(token['refresh_token']),
'expires_in': token['expires_in'],
'response_timestamp': time.time(),
'connector_relative_url': self.getRelativeUrl(),
}
def _getAuthorizationState(self):
alphabet = string.ascii_letters + string.digits
state = ''.join(random.SystemRandom().choice(alphabet) for _ in range(32))
self.getPortalObject().portal_sessions['google_login_auth_state'][state] = True
return state
def _verifyAuthorizationState(self, state):
if not self.getPortalObject().portal_sessions['google_login_auth_state'].pop(state, False):
raise Unauthorized
def _getTimeout(self):
"""Compute the time left according to publisher deadline.
"""
time_left = getTimeLeft()
if time_left is None:
time_left = DEFAULT_HTTP_TIMEOUT
return min(self.getTimeout() or DEFAULT_HTTP_TIMEOUT, time_left)
......@@ -2,13 +2,13 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Extension Component" module="erp5.portal_type"/>
<global name="Document Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>GoogleLoginUtility</string> </value>
<value> <string>GoogleConnector</string> </value>
</item>
<item>
<key> <string>description</string> </key>
......@@ -18,11 +18,7 @@
</item>
<item>
<key> <string>id</string> </key>
<value> <string>extension.erp5.GoogleLoginUtility</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Extension Component</string> </value>
<value> <string>document.erp5.GoogleConnector</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
......
import json
import oauth2client.client
import oauth2client.transport
from Products.ERP5Security.ERP5ExternalOauth2ExtractionPlugin import getGoogleUserEntry
from zExceptions import Unauthorized
SCOPE_LIST = ['https://www.googleapis.com/auth/userinfo.profile',
'https://www.googleapis.com/auth/userinfo.email']
# Default timeout (in seconds) for the HTTP request made to google servers to
# exchange the authorization code for a token.
DEFAULT_HTTP_TIMEOUT = 10
def _getGoogleClientIdAndSecretKey(portal, reference="default"):
"""Returns google client id and secret key.
Internal function.
"""
result_list = unrestrictedSearchGoogleConnector(portal, reference=reference)
assert result_list, "Google Connector not found"
if len(result_list) == 2:
raise ValueError("Impossible to select one Google Connector")
google_connector = result_list[0].getObject()
return google_connector.getClientId(), google_connector.getSecretKey()
def redirectToGoogleLoginPage(self):
client_id, secret_key = _getGoogleClientIdAndSecretKey(self.getPortalObject())
flow = oauth2client.client.OAuth2WebServerFlow(
client_id=client_id,
client_secret=secret_key,
scope=SCOPE_LIST,
redirect_uri="{0}/ERP5Site_receiveGoogleCallback".format(self.absolute_url()),
access_type="offline",
prompt="consent",
include_granted_scopes="true")
self.REQUEST.RESPONSE.redirect(flow.step1_get_authorize_url())
def getAccessTokenFromCode(self, code, redirect_uri, timeout=DEFAULT_HTTP_TIMEOUT):
client_id, secret_key = _getGoogleClientIdAndSecretKey(self.getPortalObject())
flow = oauth2client.client.OAuth2WebServerFlow(
client_id=client_id,
client_secret=secret_key,
scope=SCOPE_LIST,
redirect_uri=redirect_uri,
access_type="offline",
include_granted_scopes="true")
credential = flow.step2_exchange(
code,
http=oauth2client.transport.get_http_object(timeout=timeout))
credential_data = json.loads(credential.to_json())
return credential_data
def unrestrictedSearchGoogleConnector(self, reference="default"):
return self.getPortalObject().portal_catalog.unrestrictedSearchResults(
portal_type="Google Connector",
reference=reference,
validation_state="validated",
limit=2)
def unrestrictedSearchGoogleLogin(self, login, REQUEST=None):
if REQUEST is not None:
raise Unauthorized
return self.getPortalObject().portal_catalog.unrestrictedSearchResults(
portal_type="Google Login",
reference=login,
validation_state="validated", limit=1)
def getUserEntry(access_token):
return getGoogleUserEntry(access_token)
\ No newline at end of file
<property_sheet_list>
<portal_type id="Google Connector">
<item>OAuthClient</item>
<item>SocketClient</item>
</portal_type>
<portal_type id="Template Tool">
<item>TemplateToolERP5GoogleExtractionPluginConstraint</item>
......
......@@ -40,7 +40,7 @@
</item>
<item>
<key> <string>type_class</string> </key>
<value> <string>XMLObject</string> </value>
<value> <string>GoogleConnector</string> </value>
</item>
<item>
<key> <string>type_interface</string> </key>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ExternalMethod" module="Products.ExternalMethod.ExternalMethod"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_function</string> </key>
<value> <string>getAccessTokenFromCode</string> </value>
</item>
<item>
<key> <string>_module</string> </key>
<value> <string>GoogleLoginUtility</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>ERP5Site_getAccessTokenFromCode</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
portal = context.getPortalObject()
result_list = portal.portal_catalog(
portal_type="Google Connector",
reference=reference,
validation_state="validated",
limit=2)
if len(result_list) != 1:
raise ValueError("Impossible to select one Google Connector")
return result_list[0].getObject()
......@@ -50,19 +50,19 @@
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>login, REQUEST=None</string> </value>
<value> <string>reference="default"</string> </value>
</item>
<item>
<key> <string>_proxy_roles</string> </key>
<value>
<tuple>
<string>Manager</string>
<string>Auditor</string>
</tuple>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>ERP5Site_getPersonFromGoogleLogin</string> </value>
<value> <string>ERP5Site_getDefaultGoogleConnector</string> </value>
</item>
</dictionary>
</pickle>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ExternalMethod" module="Products.ExternalMethod.ExternalMethod"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_function</string> </key>
<value> <string>unrestrictedSearchGoogleConnector</string> </value>
</item>
<item>
<key> <string>_module</string> </key>
<value> <string>GoogleLoginUtility</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>ERP5Site_getGoogleConnector</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ExternalMethod" module="Products.ExternalMethod.ExternalMethod"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_function</string> </key>
<value> <string>unrestrictedSearchGoogleConnector</string> </value>
</item>
<item>
<key> <string>_module</string> </key>
<value> <string>GoogleLoginUtility</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>ERP5Site_getGoogleLogin</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ExternalMethod" module="Products.ExternalMethod.ExternalMethod"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_function</string> </key>
<value> <string>getUserEntry</string> </value>
</item>
<item>
<key> <string>_module</string> </key>
<value> <string>GoogleLoginUtility</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>ERP5Site_getGoogleUserEntry</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
from zExceptions import Unauthorized
if REQUEST is not None:
raise Unauthorized
login = context.ERP5Site_getGoogleLogin(login)
if login is None:
return login
if len(login) > 1:
raise ValueError("Duplicated User")
return login[0].getParentValue().getRelativeUrl()
import time
from Products.ERP5Type.Utils import str2bytes
portal = context.getPortalObject()
request = container.REQUEST
response = request.RESPONSE
......@@ -16,26 +17,21 @@ if error is not None:
return handleError(error)
elif code is not None:
response_dict = context.ERP5Site_getAccessTokenFromCode(
code,
"{0}/ERP5Site_receiveGoogleCallback".format(context.absolute_url()))
if response_dict is not None:
access_token = response_dict['access_token'].encode('utf-8')
hash_str = context.Base_getHMAC(access_token, access_token)
context.setAuthCookie(response, '__ac_google_hash', hash_str)
# store timestamp in second since the epoch in UTC is enough
response_dict["response_timestamp"] = time.time()
context.Base_setBearerToken(hash_str,
google_connector = portal.ERP5Site_getDefaultGoogleConnector()
response_dict = google_connector.getTokenFromCode(
state=state,
code=code,
redirect_uri="{}/ERP5Site_receiveGoogleCallback".format(portal.absolute_url()),
)
access_token = str2bytes(response_dict['access_token'])
hash_str = portal.Base_getHMAC(access_token, access_token)
portal.setAuthCookie(response, '__ac_google_hash', hash_str)
portal.Base_setBearerToken(
hash_str,
response_dict,
"google_server_auth_token_cache_factory")
user_dict = context.ERP5Site_getGoogleUserEntry(access_token)
user_reference = user_dict["email"]
context.Base_setBearerToken(access_token,
{"reference": user_reference},
"google_server_auth_token_cache_factory")
method = getattr(context, "ERP5Site_createGoogleUserToOAuth", None)
if method is not None:
method(user_reference, user_dict)
# XXX for ERP5JS web sites without a rewrite rule, we make sure there's a trailing /
return response.redirect(request.get("came_from") or context.absolute_url() + '/')
......
......@@ -50,7 +50,7 @@
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>code=None, error=None</string> </value>
<value> <string>code=None, state=None, error=None</string> </value>
</item>
<item>
<key> <string>id</string> </key>
......
portal = context.getPortalObject()
google_connector = portal.ERP5Site_getDefaultGoogleConnector()
return google_connector.redirectToGoogleLoginPage(
"{0}/ERP5Site_receiveGoogleCallback".format(portal.absolute_url()),
RESPONSE=RESPONSE,
)
......@@ -2,25 +2,67 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ExternalMethod" module="Products.ExternalMethod.ExternalMethod"/>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_function</string> </key>
<value> <string>redirectToGoogleLoginPage</string> </value>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>_module</string> </key>
<value> <string>GoogleLoginUtility</string> </value>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>ERP5Site_redirectToGoogleLoginPage</string> </value>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>RESPONSE</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
<key> <string>_proxy_roles</string> </key>
<value>
<tuple>
<string>Auditor</string>
</tuple>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>ERP5Site_redirectToGoogleLoginPage</string> </value>
</item>
</dictionary>
</pickle>
......
document.erp5.GoogleConnector
\ No newline at end of file
extension.erp5.GoogleLoginUtility
\ No newline at end of file
Google Connector | OAuthClient
Google Connector | SocketClient
Template Tool | TemplateToolERP5GoogleExtractionPluginConstraint
\ No newline at end of file
......@@ -92,7 +92,6 @@
element_data,
sub_element,
a_element,
a_properties,
sub_element_list,
td_element_list,
tr_element_list = [];
......@@ -157,13 +156,9 @@
if (cell.editable || !cell.href) {
sub_element_list.push(sub_element);
} else {
a_properties = {
a_element = domsugar('a', {
"href": cell.href
};
if (cell.onclick) {
a_properties.onclick = cell.onclick;
}
a_element = domsugar('a', a_properties, [sub_element]);
}, [sub_element]);
sub_element_list.push(a_element);
}
......@@ -1000,9 +995,6 @@
if (value.url_value.command) {
url_value = line_link_list[counter + index];
index += 1;
} else if (value.url_value.onclick) {
url_value = false;
value.onclick = value.url_value.onclick;
} else {
url_value = false;
}
......
......@@ -228,7 +228,7 @@
</item>
<item>
<key> <string>actor</string> </key>
<value> <unicode>zope</unicode> </value>
<value> <string>zope</string> </value>
</item>
<item>
<key> <string>comment</string> </key>
......@@ -242,7 +242,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>1016.40877.17868.16571</string> </value>
<value> <string>994.13949.44825.36573</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -262,7 +262,7 @@
</tuple>
<state>
<tuple>
<float>1715876236.83</float>
<float>1629394496.1</float>
<string>UTC</string>
</tuple>
</state>
......
<!DOCTYPE html>
<html>
<!--
data-i18n=Active Preference
data-i18n=Preferences
data-i18n=Language
data-i18n=Profile
......
......@@ -240,7 +240,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>994.61047.58814.54169</string> </value>
<value> <string>994.62318.46378.10649</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -260,7 +260,7 @@
</tuple>
<state>
<tuple>
<float>1632221574.49</float>
<float>1716899361.99</float>
<string>UTC</string>
</tuple>
</state>
......
......@@ -29,6 +29,7 @@
return RSVP.hash({
translation: gadget.getTranslationDict([
'Active Preference',
'Preferences',
'Language',
'Profile',
......@@ -50,8 +51,6 @@
// Calculate user name
if (result === undefined) {
user = null;
} else if (result.data.rows.length === 0) {
user = null;
} else {
user = result.data.rows[0].value.title;
}
......@@ -60,8 +59,10 @@
url_dict: gadget.getUrlForDict({
// Back url
back: {command: 'history_previous'},
preference: {command: 'push_history',
my_preference: {command: 'push_history',
options: {page: "preference"}},
portal_preference: {command: 'push_history',
options: {jio_key: "portal_preferences"}},
person: {command: 'push_history',
options: {jio_key: me_relative_url}},
// Change language
......@@ -75,7 +76,11 @@
domsugar(gadget.element.querySelector('.document_list'), [
domsugar('ul', {'class': 'document-listview'}, [
domsugar('li', [
domsugar('a', {href: result_dict.url_dict.preference,
domsugar('a', {href: result_dict.url_dict.my_preference,
text: result_dict.translation['Active Preference']})
]),
domsugar('li', [
domsugar('a', {href: result_dict.url_dict.portal_preference,
text: result_dict.translation.Preferences})
]),
(me_relative_url === undefined) ? '' :
......
......@@ -236,7 +236,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>998.18207.59213.64375</string> </value>
<value> <string>1014.4857.18905.5273</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -256,7 +256,7 @@
</tuple>
<state>
<tuple>
<float>1667992189.61</float>
<float>1716899348.27</float>
<string>UTC</string>
</tuple>
</state>
......
......@@ -222,7 +222,7 @@
}
var source_title = entry.value[gadget.state.source_column] || '',
attachment_list = entry.value
.DiscussionPost_getAttachmentList || [],
.Event_getAttachmentList || [],
attachment_element_list = [],
j,
word_list = source_title.split(' '),
......@@ -241,7 +241,10 @@
text: attachment_list[j].title,
href: attachment_list[j].url,
download: attachment_list[j].title
})
}),
' (',
attachment_list[j].content_type || 'application/octet-stream',
')'
])
);
}
......@@ -317,7 +320,7 @@
limit: limit_options,
select_list: ['asStrippedHTML', gadget.state.date_column,
gadget.state.source_column,
'DiscussionPost_getAttachmentList'],
'Event_getAttachmentList'],
sort_on: [[gadget.state.date_column, 'ASC'], ['uid', 'ASC']]
})
.push(function (result) {
......
......@@ -238,7 +238,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>1010.61000.1041.39372</string> </value>
<value> <string>1017.21412.29767.13277</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -258,7 +258,7 @@
</tuple>
<state>
<tuple>
<float>1693928044.6</float>
<float>1718640624.19</float>
<string>UTC</string>
</tuple>
</state>
......
return context.File_viewAsWeb(REQUEST=REQUEST, response=response, mapping_dict=mapping_dict)
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>REQUEST=None, response=None, mapping_dict=None</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>OOoDocument_viewAsWeb</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
return context.File_viewAsWeb(REQUEST=REQUEST, response=response, mapping_dict=mapping_dict)
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>REQUEST=None, response=None, mapping_dict=None</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>PDF_viewAsWeb</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -19,7 +19,7 @@
<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/click_on_panel_link" />
</tal:block>
<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/wait_for_content_loaded" />
<tal:block tal:define="click_configuration python: {'text': 'Preferences'}">
<tal:block tal:define="click_configuration python: {'text': 'Active Preference'}">
<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/click_on_page_link" />
</tal:block>
<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/wait_for_content_loaded" />
......
......@@ -21,7 +21,7 @@
<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/wait_for_content_loaded" />
<tr>
<td>assertElementPresent</td>
<td>//ul[@class="ui-list-grid"]/li[2]/h2[text()="Tools"]</td>
<td>//ul[@class="ui-list-grid"]//li/h2[text()="Tools"]</td>
<td></td>
</tr>
<tr>
......@@ -33,7 +33,7 @@
<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/click_on_panel_link" />
</tal:block>
<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/wait_for_content_loaded" />
<tal:block tal:define="click_configuration python: {'text': 'Preferences'}">
<tal:block tal:define="click_configuration python: {'text': 'Active Preference'}">
<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/click_on_page_link" />
</tal:block>
<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/wait_for_content_loaded" />
......@@ -53,7 +53,7 @@
<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/wait_for_content_loaded" />
<tr>
<td>assertElementNotPresent</td>
<td>//ul[@class="ui-list-grid"]/li[2]/h2[text()="Tools"]</td>
<td>//ul[@class="ui-list-grid"]//li/h2[text()="Tools"]</td>
<td></td>
</tr>
</tbody></table>
......
......@@ -27,7 +27,13 @@
<tr>
<td>assertElementPresent</td>
<td>//div[@data-gadget-scope='m']//a[text()='Preferences' and contains(@href, '#!push_history') and contains(@href, 'n.page=preference')]</td>
<td>//div[@data-gadget-scope='m']//a[text()='Active Preference' and contains(@href, '#!push_history') and contains(@href, 'n.page=preference')]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//div[@data-gadget-scope='m']//a[text()='Preferences' and contains(@href, '#!push_history') and contains(@href, 'n.jio_key=portal_preferences')]</td>
<td></td>
</tr>
......
......@@ -39,6 +39,7 @@ if related:
"that_title": context.getTitleOrId() }),)
return module.Base_redirect(
'view', keep_items={'%s__uid' % base_category: relation.getUid(),
'portal_type': portal_type,
'ignore_hide_rows': 1,
'reset': 1,
'portal_status_message': message})
......
from zExceptions import Unauthorized
if REQUEST is not None:
raise Unauthorized
portal = context.getPortalObject()
alarm_tool = portal.portal_alarms
# Higher than simulable movement priority
# priority=3, to be executed after all reindex, but also execute simulation _expand
PRIORITY = 3
if alarm_tool.isSubscribed() and len(alarm_id_list):
# No alarm tool is not subscribed, respect this choice and do not activate any alarm
tag = None
if must_reindex_context:
tag = "%s-%s" % (script.id, context.getRelativeUrl())
context.reindexObject(activate_kw={'tag': tag})
for alarm_id in alarm_id_list:
alarm = alarm_tool.restrictedTraverse(alarm_id)
deduplication_tag = 'Base_reindexAndSenseAlarm_%s' % alarm_id
if alarm.isEnabled():
# do nothing if the alarm is not enabled
if tag is not None:
activate_kw = {}
activate_kw['activity'] = 'SQLQueue'
activate_kw['after_tag'] = tag
activate_kw['tag'] = deduplication_tag
activate_kw['priority'] = max(1, PRIORITY-1)
# Wait for the context indexation to be finished
alarm_tool.activate(**activate_kw).Base_reindexAndSenseAlarm([alarm_id],
must_reindex_context=False)
elif portal.portal_activities.countMessageWithTag(deduplication_tag) <= 1:
if alarm.isActive():
# If the alarm is active, wait for it
# and try to reduce the number of activities
# to reduce the number of alarm execution
activate_kw = {}
activate_kw['activity'] = 'SQLQueue'
activate_kw['priority'] = PRIORITY
activate_kw['tag'] = deduplication_tag
activate_kw['after_path'] = alarm.getPath()
# Wait for the previous alarm run to be finished
# call on alarm tool to gather and drop with sqldict
alarm_tool.activate(**activate_kw).Base_reindexAndSenseAlarm([alarm_id],
must_reindex_context=False)
else:
# activeSense create an activity in SQLDict
alarm.activeSense()
# Prevent 2 nodes to call activateSense concurrently
alarm.serialize()
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>alarm_id_list, must_reindex_context=True, REQUEST=None</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Base_reindexAndSenseAlarm</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
from Products.ERP5Type.Utils import getMessageIdWithContext
from Products.ERP5Type.Utils import getMessageIdWithContext, str2unicode, unicode2str
supported_languages = context.Localizer.get_supported_languages()
translated_keys = {} # This dict prevents entering the same key twice
......@@ -34,7 +34,7 @@ for portal_type in portal_type_list:
for lang in supported_languages:
key = (lang, portal_type.getId(), state_var, state_reference)
if key not in translated_keys:
translated_message = context.Localizer.erp5_ui.gettext(state_reference, lang=lang).encode('utf-8')
translated_message = unicode2str(context.Localizer.erp5_ui.gettext(state_reference, lang=lang))
translated_keys[key] = None # mark as translated
object_list.append(dict(language=lang, message_context=state_var, portal_type=portal_type.getId(), original_message=state_reference,
translated_message=translated_message))
......@@ -43,10 +43,10 @@ for portal_type in portal_type_list:
if state.getTitle() is not None and state.getTitle() != '':
state_var_title = '%s_title' % state_var
msg_id = getMessageIdWithContext(state.getTitle(), 'state', wf_id)
translated_message = context.Localizer.erp5_ui.gettext(msg_id, default='', lang=lang).encode('utf-8')
translated_message = unicode2str(context.Localizer.erp5_ui.gettext(msg_id, default='', lang=lang))
if translated_message == '':
msg_id = state.getTitle()
translated_message = context.Localizer.erp5_ui.gettext(state.getTitle().decode('utf-8'), lang=lang).encode('utf-8')
translated_message = unicode2str(context.Localizer.erp5_ui.gettext(str2unicode(state.getTitle()), lang=lang))
key = (lang, portal_type.getId(), state_var_title, state_reference, msg_id)
if key not in translated_keys:
translated_keys[key] = None # mark as translated
......@@ -67,7 +67,7 @@ for ptype in context.portal_types.objectValues():
if key not in translated_keys:
translated_keys[key] = None # mark as translated
object_list.append(dict(language=lang, message_context='portal_type', portal_type=portal_type, original_message=portal_type,
translated_message=context.Localizer.erp5_ui.gettext(portal_type, lang=lang).encode('utf-8')))
translated_message=unicode2str(context.Localizer.erp5_ui.gettext(portal_type, lang=lang))))
if object_list:
catalog_translation_list(object_list)
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Test Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>testERP5CoreSkins</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>test.erp5.testERP5CoreSkins</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
test.erp5.testERP5CoreSkins
\ No newline at end of file
erp5_full_text_mroonga_catalog
erp5_simulation_test
\ No newline at end of file
......@@ -8,9 +8,7 @@
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value>
<none/>
</value>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
......
......@@ -8,9 +8,7 @@
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value>
<none/>
</value>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>jquery.js</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>bender-runner.config.json</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>build-config.js</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>ckeditor.js</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>config.js</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>contents.css</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>af.js</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>ar.js</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>az.js</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>bg.js</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>bn.js</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>bs.js</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>ca.js</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>cs.js</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>cy.js</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>da.js</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>de-ch.js</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>de.js</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>el.js</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>en-au.js</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>en-ca.js</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>en-gb.js</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>en.js</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>eo.js</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>es-mx.js</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>es.js</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>et.js</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>eu.js</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>fa.js</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>fi.js</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>fo.js</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>fr-ca.js</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>fr.js</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>gl.js</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>gu.js</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>he.js</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>hi.js</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>hr.js</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>hu.js</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>id.js</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>is.js</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>it.js</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>ja.js</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>ka.js</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>km.js</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>ko.js</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>ku.js</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>lt.js</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>lv.js</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>mk.js</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>mn.js</string> </value>
......
......@@ -6,6 +6,10 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>ms.js</string> </value>
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment