+
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 66 additions & 5 deletions deform/field.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# Standard Library
import itertools
import re
from typing import Optional
import unicodedata
import weakref

Expand Down Expand Up @@ -126,6 +127,29 @@ class Field(object):
``autofocus`` set to a true-ish value (``on``, ``True``, or
``autofocus``) will receive focus on page load. Default: ``None``.

script_nonce
Nonce (number-used-once) for use with ``<script>`` tags via the
HTTP Content-Security-Policy (CSP) header system. If the CSP header
requires that inline Javascript is tagged with a relevant nonce,
pass it here to apply this nonce to ``<script>`` tags only, or
via the ``nonce`` argument (if it should be applied to all tags
supporting nonces).

style_nonce
Nonce (number-used-once) for use with ``<style>`` tags via the
HTTP Content-Security-Policy (CSP) header system. If the CSP header
requires that inline Javascript is tagged with a relevant nonce,
pass it here to apply this nonce to ``<style>`` tags only, or
via the ``nonce`` argument (if it should be applied to all tags
supporting nonces).

nonce
Content-Security-Policy (CSP) nonce to be applied to all tags
supporting a ``nonce`` attribute, currently supported for
``<script>`` and ``<style>``. See also ``script_nonce``,
``style_nonce``. Specifying ``nonce`` overrides the more specific
options.

*Constructor Arguments*

``renderer``, ``counter``, ``resource_registry`` and ``appstruct`` are
Expand Down Expand Up @@ -183,6 +207,9 @@ def __init__(
appstruct=colander.null,
parent=None,
autofocus=None,
script_nonce: str = None,
style_nonce: str = None,
nonce: str = None,
**kw
):
self.counter = counter or itertools.count()
Expand All @@ -199,6 +226,12 @@ def __init__(
if resource_registry is None:
resource_registry = self.default_resource_registry
self.renderer = renderer
if nonce:
self.script_nonce = nonce
self.style_nonce = nonce
else:
self.script_nonce = script_nonce
self.style_nonce = style_nonce

# Parameters passed from parent field to child
if "focus" in kw:
Expand Down Expand Up @@ -269,19 +302,19 @@ def __init__(
self.set_appstruct(appstruct)

def found_first(self):
""" Set have_first_input of ancestors """
"""Set have_first_input of ancestors"""
self.have_first_input = True
if self.parent is not None:
self.parent.found_first()

@property
def parent(self):
def parent(self) -> Optional["Field"]:
if self._parent is None:
return None
return self._parent()

def get_root(self):
""" Return the root field in the field hierarchy (the form field) """
"""Return the root field in the field hierarchy (the form field)"""
node = self
while True:
parent = node.parent
Expand Down Expand Up @@ -353,7 +386,7 @@ def translate(self, msgid):
return msgid

def __iter__(self):
""" Iterate over the children fields of this field. """
"""Iterate over the children fields of this field."""
return iter(self.children)

def __getitem__(self, name):
Expand Down Expand Up @@ -381,6 +414,8 @@ def clone(self):
cloned.__dict__.update(self.__dict__)
cloned.order = next(cloned.counter)
cloned.oid = "deformField%s" % cloned.order
cloned.script_nonce = self.script_nonce_recursive
cloned.style_nonce = self.style_nonce_recursive
cloned._parent = None
children = []
for field in self.children:
Expand Down Expand Up @@ -626,7 +661,7 @@ def serialize(self, cstruct=_marker, **kw):
return self.widget.serialize(**values)

def deserialize(self, pstruct):
""" Deserialize the pstruct into a cstruct and return the cstruct."""
"""Deserialize the pstruct into a cstruct and return the cstruct."""
return self.widget.deserialize(self, pstruct)

def render(self, appstruct=_marker, **kw):
Expand Down Expand Up @@ -924,3 +959,29 @@ def end_rename(self, name=None):
name = self.name
tag = '<input type="hidden" name="__end__" value="%s:rename"/>'
return Markup(tag % (name,))

@property
def script_nonce_recursive(self) -> Optional[str]:
"""
Returns the CSP nonce for ``<script>`` tags or, if ``self`` doesn't
have one, its parent (until we find one or reach the topmost
parent).
"""
if self.script_nonce:
return self.script_nonce
if self.parent:
return self.parent.script_nonce_recursive
return None

@property
def style_nonce_recursive(self) -> Optional[str]:
"""
Returns the CSP nonce for ``<style>`` tags or, if ``self`` doesn't
have one, its parent (until we find one or reach the topmost
parent).
"""
if self.style_nonce:
return self.style_nonce
if self.parent:
return self.parent.style_nonce_recursive
return None
37 changes: 24 additions & 13 deletions deform/static/scripts/deform.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,20 @@ var deform = {
},

load: function() {
$(function() {
if (!deform_loaded) {
deform.processCallbacks();
deform_loaded = true;
}});
$(function() {
if (!deform_loaded) {
deform.processCallbacks();
deform_loaded = true;
}
});
},

processCallbacks: function () {
$(deform.callbacks).each(function(num, item) {
var oid = item[0];
var callback = item[1];
callback(oid);
}
);
});
deform.clearCallbacks();
},

Expand Down Expand Up @@ -73,7 +73,7 @@ var deform = {
var labelselector = 'label[for=' + oldid + ']';
var $fornodes = $htmlnode.find(labelselector);
$fornodes.attr('for', newid);
});
});

// replace names a containing ```deformField`` like we do for ids

Expand All @@ -82,7 +82,7 @@ var deform = {
var oldname = $node.attr('name');
var newname = oldname.replace(fieldmatch, "deformField$1-" + genid);
$node.attr('name', newname);
});
});

$htmlnode.insertBefore(before);

Expand All @@ -92,8 +92,8 @@ var deform = {
var newid = idmap[oid];
if (newid) {
callback(newid);
}
});
}
});

deform.clearCallbacks();
var old_len = parseInt(before.attr('now_len')||'0', 10);
Expand All @@ -112,7 +112,7 @@ var deform = {
var orderable = parseInt($before_node.attr('orderable')||'0', 10);

if (now_len < max_len) {
deform.addSequenceItem($proto_node, $before_node);
deform.addSequenceItem($proto_node, $before_node);
deform.processSequenceButtons($oid_node, min_len, max_len,
now_len + 1, orderable);
}
Expand Down Expand Up @@ -149,10 +149,21 @@ var deform = {
$lis.find('.deform-close-button').not($lis.find('.deform-seq-container .deform-close-button')).toggle(show_closebutton);
oid_node.find('.deform-seq-add').not(oid_node.find('.deform-seq-container .deform-seq-add')).toggle(show_addbutton);
$lis.find('.deform-order-button').not($lis.find('.deform-seq-container .deform-order-button')).toggle(orderable && has_multiple);
// Since "onclick" isn't OK with restricted content security policy,
// we add the click handler here, removing the need for evaluation of
// item prototype code that containts Javascript.
// - for pre-existing items, the click handler is added at page
// creation via processSequenceButtons(), thanks to a
// deform.addCallback call in sequence.pt;
// - for newly created items (added by the user), we get here via
// appendSequenceItem().
$lis.find('.deform-close-button').click(function () {
deform.removeSequenceItem(this);
});
},

randomString: function (length) {
var chr='0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz';
var chr = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz';
chr = chr.split('');

if (! length) {
Expand Down
2 changes: 1 addition & 1 deletion deform/templates/autocomplete_input.pt
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
autofocus autofocus;
attributes|field.widget.attributes|{};"
id="${oid}"/>
<script tal:condition="field.widget.values" type="text/javascript">
<script tal:condition="field.widget.values" type="text/javascript" nonce="${field.script_nonce_recursive}">
deform.addCallback(
'${field.oid}',
function (oid) {
Expand Down
2 changes: 1 addition & 1 deletion deform/templates/checked_input.pt
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
confirm_attributes|field.widget.confirm_attributes|{};"
id="${oid}-confirm"/>
</div>
<script tal:condition="field.widget.mask" type="text/javascript">
<script tal:condition="field.widget.mask" type="text/javascript" nonce="${field.script_nonce_recursive}">
deform.addCallback(
'${oid}',
function (oid) {
Expand Down
2 changes: 1 addition & 1 deletion deform/templates/dateinput.pt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
attributes|field.widget.attributes|{};"
id="${oid}"/>
${field.end_mapping()}
<script type="text/javascript">
<script type="text/javascript" nonce="${field.script_nonce_recursive}">
deform.addCallback(
'${oid}',
function deform_cb(oid) {
Expand Down
2 changes: 1 addition & 1 deletion deform/templates/datetimeinput.pt
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
</div></div>
</div>
${field.end_mapping()}
<script type="text/javascript">
<script type="text/javascript" nonce="${field.script_nonce_recursive}">
deform.addCallback(
'${oid}',
function(oid) {
Expand Down
2 changes: 1 addition & 1 deletion deform/templates/file_upload.pt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
tal:condition="uid"
type="hidden" name="uid" value="${uid}"/>
${field.end_mapping()}
<script type="text/javascript">
<script type="text/javascript" nonce="${field.script_nonce_recursive}">
deform.addCallback('${oid}', function (oid) {
$('#' + oid).upload();
});
Expand Down
2 changes: 1 addition & 1 deletion deform/templates/form.pt
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@

</fieldset>

<script type="text/javascript" tal:condition="use_ajax">
<script type="text/javascript" tal:condition="use_ajax" nonce="${field.script_nonce_recursive}">
deform.addCallback(
'${formid}',
function(oid) {
Expand Down
2 changes: 1 addition & 1 deletion deform/templates/moneyinput.pt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
autofocus autofocus;
attributes|field.widget.attributes|{};"
id="${oid}"/>
<script type="text/javascript">
<script type="text/javascript" nonce="${field.script_nonce_recursive}">
deform.addCallback(
'${oid}',
function (oid) {
Expand Down
4 changes: 2 additions & 2 deletions deform/templates/richtext.pt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
i18n:domain="deform"
tal:omit-tag="">

<style type="text/css">
<style type="text/css" nonce="${field.style_nonce_recursive}">
.deform .tinymce-preload{
border: 1px solid #CCC;
height: 240px;
Expand All @@ -23,7 +23,7 @@
<span id="${oid}-preload" class="tinymce-preload"
tal:condition="delayed_load and not field.error"
tal:content="structure cstruct" />
<script type="text/javascript">
<script type="text/javascript" nonce="${field.script_nonce_recursive}">
(function($){
deform.addCallback('${oid}', function(oid) {
var options = {
Expand Down
4 changes: 2 additions & 2 deletions deform/templates/select2.pt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
autofocus autofocus|field.autofocus"
tal:omit-tag="">

<style>
<style nonce="${field.style_nonce_recursive}">

.select2-selection.form-control {
padding: 0px 0px;
Expand Down Expand Up @@ -52,7 +52,7 @@
</tal:loop>
</select>

<script type="text/javascript">
<script type="text/javascript" nonce="${field.script_nonce_recursive}">
deform.addCallback(
'${field.oid}',
function(oid) {
Expand Down
2 changes: 1 addition & 1 deletion deform/templates/selectize.pt
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
</tal:loop>
</select>

<script type="text/javascript">
<script type="text/javascript" nonce="${field.script_nonce_recursive}">
deform.addCallback(
"${field.oid}",
function(oid) {
Expand Down
Loading
点击 这是indexloc提供的php浏览器服务,不要输入任何密码和下载