} else if (jsValue.children().size() == 1) {
// Declarations have been reduced to a single, statically known
// StringLiteral or dynamically computed Expression
dynamicValue = jsValue.children().get(0);
} else {
throw new SomethingWidgyHappenedError(
"Rewriter thinks STYLE attribute should contain plugin ID");
}
break;
case URI:
if (attributeContent.containsKey(attr.src)) { // A javascript: URI
Block b = this.jsFromAttrib(attr);
if (b == null || b.children().isEmpty()) { return noResult(attr); }
String handlerIndexName = meta.generateUniqueName("c");
Identifier handlerIndex = SyntheticNodes.s(new Identifier(
FilePosition.UNKNOWN, handlerIndexName));
Statement handler = (Statement) QuasiBuilder.substV(
""
+ "var @handlerIndex = IMPORTS___.handlers___.push("
+ " ___./*@synthetic*/markFuncFreeze("
// There is no node or event object available to code in
// javascript: URIs.
+ " /*@synthetic*/function () { @body*; })) - 1;",
"handlerIndex", handlerIndex,
"body", new ParseTreeNodeContainer(b.children()));
handlers.add(new EventHandler(attr.env, handler));
handlerCache.put(value, handlerIndexName);
Operation urlAdapter = (Operation) QuasiBuilder.substV(
""
+ "'javascript:' + /*@synthetic*/encodeURIComponent("
+ " 'try{void ___.plugin_dispatchToHandler___('"
+ " + ___./*@synthetic*/getId(IMPORTS___)"
+ " + ',' + @handlerIndex + ',[{}])}catch(_){}')",
"handlerIndex", new Reference(handlerIndex));
urlAdapter.setFilePosition(pos);
urlAdapter.getAttributes().set(HANDLER_NAME, handlerIndexName);
dynamicValue = urlAdapter;
} else {
URI uri;
try {
uri = new URI(UriUtil.normalizeUri(value));
} catch (URISyntaxException ex) {
mq.addMessage(
IhtmlMessageType.MALFORMED_URI, pos,
MessagePart.Factory.valueOf(value));
return noResult(attr);
}
if (meta.getUriPolicy() != null) {
ExternalReference ref = new ExternalReference(uri, pos);
String rewrittenUri = UriPolicyNanny.apply(
meta.getUriPolicy(),
ref, attr.attrInfo.getUriEffect(),
attr.attrInfo.getLoaderType(),
Collections.singletonMap(
UriPolicyHintKey.XML_ATTR.key,
attr.attrInfo.getKey().toString()));
if (rewrittenUri == null) {
mq.addMessage(
PluginMessageType.DISALLOWED_URI, pos,
MessagePart.Factory.valueOf(uri.toString()));
return noResult(attr);
}
dynamicValue = StringLiteral.valueOf(
ref.getReferencePosition(), rewrittenUri);
} else {
dynamicValue = (Expression) QuasiBuilder.substV(
""
+ "IMPORTS___./*@synthetic*/rewriteUriInAttribute___("
+ " @value, @tagName, @attribName)",
"value", new StringLiteral(
pos, uri.toString()),
"tagName", new StringLiteral(
pos, attr.src.getOwnerElement().getTagName()),
"attribName", new StringLiteral(
pos, attr.src.getName()));
}
}
break;
case URI_FRAGMENT:
if (value.length() < 2 || !value.startsWith("#")) {
mq.addMessage(
IhtmlMessageType.BAD_ATTRIB, pos,
attr.attrInfo.getKey().el, attr.attrInfo.getKey(),
MessagePart.Factory.valueOf(value));
return noResult(attr);
}
String id = value.substring(1);
if (!checkValidId(id, pos)) { return noResult(attr); }
JsConcatenator out = new JsConcatenator();
out.append(FilePosition.startOf(pos), "#");
rewriteIdentifiers(pos, id, out);
dynamicValue = out.toExpression(false);
break;
default:
throw new SomethingWidgyHappenedError(attr.attrInfo.getType().name());
}
return new SanitizedAttr(true, dynamicValue);
}